From e50dc17163d9a40596f0db0ff2fb0b1eaef52ff9 Mon Sep 17 00:00:00 2001 From: Bhawanpreet Lakha Date: Thu, 12 Dec 2019 16:28:23 -0500 Subject: drm/amd/display: Pass amdgpu_device instead of psp_context [Why] We need this to create sysfs (followup patch) [How] Change the parameter Signed-off-by: Bhawanpreet Lakha Reviewed-by: Rodrigo Siqueira Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 2 +- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.c | 4 ++-- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.h | 3 ++- 3 files changed, 5 insertions(+), 4 deletions(-) (limited to 'drivers/gpu/drm/amd/display') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 279541517a99..d0ddbc9df264 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -960,7 +960,7 @@ static int amdgpu_dm_init(struct amdgpu_device *adev) #ifdef CONFIG_DRM_AMD_DC_HDCP if (adev->asic_type >= CHIP_RAVEN) { - adev->dm.hdcp_workqueue = hdcp_create_workqueue(&adev->psp, &init_params.cp_psp, adev->dm.dc); + adev->dm.hdcp_workqueue = hdcp_create_workqueue(adev, &init_params.cp_psp, adev->dm.dc); if (!adev->dm.hdcp_workqueue) DRM_ERROR("amdgpu: failed to initialize hdcp_workqueue.\n"); diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.c index 0acd3409dd6c..a269916f7dd6 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.c @@ -338,7 +338,7 @@ static void update_config(void *handle, struct cp_psp_stream_config *config) hdcp_update_display(hdcp_work, link_index, aconnector, DRM_MODE_HDCP_CONTENT_TYPE0, false); } -struct hdcp_workqueue *hdcp_create_workqueue(void *psp_context, struct cp_psp *cp_psp, struct dc *dc) +struct hdcp_workqueue *hdcp_create_workqueue(struct amdgpu_device *adev, struct cp_psp *cp_psp, struct dc *dc) { int max_caps = dc->caps.max_links; @@ -360,7 +360,7 @@ struct hdcp_workqueue *hdcp_create_workqueue(void *psp_context, struct cp_psp *c INIT_DELAYED_WORK(&hdcp_work[i].watchdog_timer_dwork, event_watchdog_timer); INIT_DELAYED_WORK(&hdcp_work[i].property_validate_dwork, event_property_validate); - hdcp_work[i].hdcp.config.psp.handle = psp_context; + hdcp_work[i].hdcp.config.psp.handle = &adev->psp; hdcp_work[i].hdcp.config.ddc.handle = dc_get_link_at_index(dc, i); hdcp_work[i].hdcp.config.ddc.funcs.write_i2c = lp_write_i2c; hdcp_work[i].hdcp.config.ddc.funcs.read_i2c = lp_read_i2c; diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.h index 6abde86bce4a..331b50825510 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.h @@ -30,6 +30,7 @@ #include "hdcp.h" #include "dc.h" #include "dm_cp_psp.h" +#include "amdgpu.h" struct mod_hdcp; struct mod_hdcp_link; @@ -64,6 +65,6 @@ void hdcp_reset_display(struct hdcp_workqueue *work, unsigned int link_index); void hdcp_handle_cpirq(struct hdcp_workqueue *work, unsigned int link_index); void hdcp_destroy(struct hdcp_workqueue *work); -struct hdcp_workqueue *hdcp_create_workqueue(void *psp_context, struct cp_psp *cp_psp, struct dc *dc); +struct hdcp_workqueue *hdcp_create_workqueue(struct amdgpu_device *adev, struct cp_psp *cp_psp, struct dc *dc); #endif /* AMDGPU_DM_AMDGPU_DM_HDCP_H_ */ -- cgit From 79aad7bd951bc1a1c797e25ad990191ff280c6c6 Mon Sep 17 00:00:00 2001 From: Bhawanpreet Lakha Date: Thu, 12 Dec 2019 16:00:01 -0500 Subject: drm/amd/display: update psp interface header [Why] We need to support SRM(System Renewability Message) As per hdcp spec (5.Renewability) SRM needs to be storage in a non-volatile memory. PSP owns the checking of SRM but doesn't have the ability to store it in a non-volatile memory. So we need the kernel driver to facilitate it using the interface provided by PSP [How] Add the interface to the header file, so the driver can use them v2: update commit description Signed-off-by: Bhawanpreet Lakha Reviewed-by: Rodrigo Siqueira Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/modules/hdcp/hdcp_psp.h | 26 +++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) (limited to 'drivers/gpu/drm/amd/display') diff --git a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_psp.h b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_psp.h index 82a5e997d573..d5cb3f46606f 100644 --- a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_psp.h +++ b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_psp.h @@ -117,6 +117,8 @@ struct ta_dtm_shared_memory { int psp_cmd_submit_buf(struct psp_context *psp, struct amdgpu_firmware_info *ucode, struct psp_gfx_cmd_resp *cmd, uint64_t fence_mc_addr); +enum { PSP_HDCP_SRM_FIRST_GEN_MAX_SIZE = 5120 }; + enum ta_hdcp_command { TA_HDCP_COMMAND__INITIALIZE, TA_HDCP_COMMAND__HDCP1_CREATE_SESSION, @@ -134,7 +136,10 @@ enum ta_hdcp_command { TA_HDCP_COMMAND__UNUSED_3, TA_HDCP_COMMAND__HDCP2_CREATE_SESSION_V2, TA_HDCP_COMMAND__HDCP2_PREPARE_PROCESS_AUTHENTICATION_MSG_V2, - TA_HDCP_COMMAND__HDCP2_ENABLE_DP_STREAM_ENCRYPTION + TA_HDCP_COMMAND__HDCP2_ENABLE_DP_STREAM_ENCRYPTION, + TA_HDCP_COMMAND__HDCP_DESTROY_ALL_SESSIONS, + TA_HDCP_COMMAND__HDCP_SET_SRM, + TA_HDCP_COMMAND__HDCP_GET_SRM }; enum ta_hdcp2_msg_id { @@ -415,6 +420,22 @@ struct ta_hdcp_cmd_hdcp2_enable_dp_stream_encryption_input { uint32_t display_handle; }; +struct ta_hdcp_cmd_set_srm_input { + uint32_t srm_buf_size; + uint8_t srm_buf[PSP_HDCP_SRM_FIRST_GEN_MAX_SIZE]; +}; + +struct ta_hdcp_cmd_set_srm_output { + uint8_t valid_signature; + uint32_t srm_version; +}; + +struct ta_hdcp_cmd_get_srm_output { + uint32_t srm_version; + uint32_t srm_buf_size; + uint8_t srm_buf[PSP_HDCP_SRM_FIRST_GEN_MAX_SIZE]; +}; + /**********************************************************/ /* Common input structure for HDCP callbacks */ union ta_hdcp_cmd_input { @@ -432,6 +453,7 @@ union ta_hdcp_cmd_input { struct ta_hdcp_cmd_hdcp2_process_prepare_authentication_message_input_v2 hdcp2_prepare_process_authentication_message_v2; struct ta_hdcp_cmd_hdcp2_enable_dp_stream_encryption_input hdcp2_enable_dp_stream_encryption; + struct ta_hdcp_cmd_set_srm_input hdcp_set_srm; }; /* Common output structure for HDCP callbacks */ @@ -444,6 +466,8 @@ union ta_hdcp_cmd_output { struct ta_hdcp_cmd_hdcp2_create_session_output_v2 hdcp2_create_session_v2; struct ta_hdcp_cmd_hdcp2_process_prepare_authentication_message_output_v2 hdcp2_prepare_process_authentication_message_v2; + struct ta_hdcp_cmd_set_srm_output hdcp_set_srm; + struct ta_hdcp_cmd_get_srm_output hdcp_get_srm; }; /**********************************************************/ -- cgit From 9037246bb2da58d7b990ec9133f69c0b7d86f7a0 Mon Sep 17 00:00:00 2001 From: Bhawanpreet Lakha Date: Thu, 12 Dec 2019 16:36:32 -0500 Subject: drm/amd/display: Add sysfs interface for set/get srm [Why] PSP doesn't have the ability to store SRM in a non-volatile memory. And since the kernel cannot write to the storage directly, we need usermode to facilitate this As per spec the SRM needs to be persistent so this interface is to be called by the usermode anytime the system goes down/powers on *boot/resume: load from storage *shutdown/suspend: save to storage [How] Provide a sysfs interface so that the usermode can set/get srm at the right times save to storage: call "cat /sys/class/drm/card0/device/hdcp_srm > file" after boot and resume -driver calls psp_get_srm() to get the stored srm and outputs it load from storage: call "cat file > /sys/class/drm/card0/device/hdcp_srm" before shutdown and suspend -driver reads the file from sysfs and calls psp_set_srm() to send the SRM to PSP v2: -update commit description -add comment about sysfs file handling in the code v3: - squash in use after free fix (Dan Carpenter) Signed-off-by: Bhawanpreet Lakha Reviewed-by: Rodrigo Siqueira Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.c | 182 ++++++++++++++++++++- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.h | 6 + 2 files changed, 185 insertions(+), 3 deletions(-) (limited to 'drivers/gpu/drm/amd/display') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.c index a269916f7dd6..221abee517ee 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.c @@ -28,6 +28,8 @@ #include "amdgpu_dm.h" #include "dm_helpers.h" #include +#include "hdcp_psp.h" + static bool lp_write_i2c(void *handle, uint32_t address, const uint8_t *data, uint32_t size) @@ -67,6 +69,16 @@ lp_read_dpcd(void *handle, uint32_t address, uint8_t *data, uint32_t size) return dm_helpers_dp_read_dpcd(link->ctx, link, address, data, size); } +static uint8_t *psp_get_srm(struct psp_context *psp, uint32_t *srm_version, uint32_t *srm_size) +{ + return NULL; +} + +static int psp_set_srm(struct psp_context *psp, uint8_t *srm, uint32_t srm_size, uint32_t *srm_version) +{ + return 0; +} + static void process_output(struct hdcp_workqueue *hdcp_work) { struct mod_hdcp_output output = hdcp_work->output; @@ -88,6 +100,18 @@ static void process_output(struct hdcp_workqueue *hdcp_work) schedule_delayed_work(&hdcp_work->property_validate_dwork, msecs_to_jiffies(0)); } +static void link_lock(struct hdcp_workqueue *work, bool lock) +{ + + int i = 0; + + for (i = 0; i < work->max_link; i++) { + if (lock) + mutex_lock(&work[i].mutex); + else + mutex_unlock(&work[i].mutex); + } +} void hdcp_update_display(struct hdcp_workqueue *hdcp_work, unsigned int link_index, struct amdgpu_dm_connector *aconnector, @@ -301,8 +325,9 @@ void hdcp_destroy(struct hdcp_workqueue *hdcp_work) cancel_delayed_work_sync(&hdcp_work[i].watchdog_timer_dwork); } + kfree(hdcp_work->srm); + kfree(hdcp_work->srm_temp); kfree(hdcp_work); - } static void update_config(void *handle, struct cp_psp_stream_config *config) @@ -338,20 +363,163 @@ static void update_config(void *handle, struct cp_psp_stream_config *config) hdcp_update_display(hdcp_work, link_index, aconnector, DRM_MODE_HDCP_CONTENT_TYPE0, false); } + +/* NOTE: From the usermodes prospective you only need to call write *ONCE*, the kernel + * will automatically call once or twice depending on the size + * + * call: "cat file > /sys/class/drm/card0/device/hdcp_srm" from usermode no matter what the size is + * + * The kernel can only send PAGE_SIZE at once and since MAX_SRM_FILE(5120) > PAGE_SIZE(4096), + * srm_data_write can be called multiple times. + * + * sysfs interface doesn't tell us the size we will get so we are sending partial SRMs to psp and on + * the last call we will send the full SRM. PSP will fail on every call before the last. + * + * This means we don't know if the SRM is good until the last call. And because of this limitation we + * cannot throw errors early as it will stop the kernel from writing to sysfs + * + * Example 1: + * Good SRM size = 5096 + * first call to write 4096 -> PSP fails + * Second call to write 1000 -> PSP Pass -> SRM is set + * + * Example 2: + * Bad SRM size = 4096 + * first call to write 4096 -> PSP fails (This is the same as above, but we don't know if this + * is the last call) + * + * Solution?: + * 1: Parse the SRM? -> It is signed so we don't know the EOF + * 2: We can have another sysfs that passes the size before calling set. -> simpler solution + * below + * + * Easy Solution: + * Always call get after Set to verify if set was successful. + * +----------------------+ + * | Why it works: | + * +----------------------+ + * PSP will only update its srm if its older than the one we are trying to load. + * Always do set first than get. + * -if we try to "1. SET" a older version PSP will reject it and we can "2. GET" the newer + * version and save it + * + * -if we try to "1. SET" a newer version PSP will accept it and we can "2. GET" the + * same(newer) version back and save it + * + * -if we try to "1. SET" a newer version and PSP rejects it. That means the format is + * incorrect/corrupted and we should correct our SRM by getting it from PSP + */ +static ssize_t srm_data_write(struct file *filp, struct kobject *kobj, struct bin_attribute *bin_attr, char *buffer, + loff_t pos, size_t count) +{ + struct hdcp_workqueue *work; + uint32_t srm_version = 0; + + work = container_of(bin_attr, struct hdcp_workqueue, attr); + link_lock(work, true); + + memcpy(work->srm_temp + pos, buffer, count); + + if (!psp_set_srm(work->hdcp.config.psp.handle, work->srm_temp, pos + count, &srm_version)) { + DRM_DEBUG_DRIVER("HDCP SRM SET version 0x%X", srm_version); + memcpy(work->srm, work->srm_temp, pos + count); + work->srm_size = pos + count; + work->srm_version = srm_version; + } + + + link_lock(work, false); + + return count; +} + +static ssize_t srm_data_read(struct file *filp, struct kobject *kobj, struct bin_attribute *bin_attr, char *buffer, + loff_t pos, size_t count) +{ + struct hdcp_workqueue *work; + uint8_t *srm = NULL; + uint32_t srm_version; + uint32_t srm_size; + size_t ret = count; + + work = container_of(bin_attr, struct hdcp_workqueue, attr); + + link_lock(work, true); + + srm = psp_get_srm(work->hdcp.config.psp.handle, &srm_version, &srm_size); + + if (!srm) + return -EINVAL; + + if (pos >= srm_size) + ret = 0; + + if (srm_size - pos < count) { + memcpy(buffer, srm + pos, srm_size - pos); + ret = srm_size - pos; + goto ret; + } + + memcpy(buffer, srm + pos, count); + +ret: + link_lock(work, false); + return ret; +} + +/* From the hdcp spec (5.Renewability) SRM needs to be stored in a non-volatile memory. + * + * For example, + * if Application "A" sets the SRM (ver 2) and we reboot/suspend and later when Application "B" + * needs to use HDCP, the version in PSP should be SRM(ver 2). So SRM should be persistent + * across boot/reboots/suspend/resume/shutdown + * + * Currently when the system goes down (suspend/shutdown) the SRM is cleared from PSP. For HDCP we need + * to make the SRM persistent. + * + * -PSP owns the checking of SRM but doesn't have the ability to store it in a non-volatile memory. + * -The kernel cannot write to the file systems. + * -So we need usermode to do this for us, which is why an interface for usermode is needed + * + * + * + * Usermode can read/write to/from PSP using the sysfs interface + * For example: + * to save SRM from PSP to storage : cat /sys/class/drm/card0/device/hdcp_srm > srmfile + * to load from storage to PSP: cat srmfile > /sys/class/drm/card0/device/hdcp_srm + */ +static const struct bin_attribute data_attr = { + .attr = {.name = "hdcp_srm", .mode = 0664}, + .size = PSP_HDCP_SRM_FIRST_GEN_MAX_SIZE, /* Limit SRM size */ + .write = srm_data_write, + .read = srm_data_read, +}; + + struct hdcp_workqueue *hdcp_create_workqueue(struct amdgpu_device *adev, struct cp_psp *cp_psp, struct dc *dc) { int max_caps = dc->caps.max_links; - struct hdcp_workqueue *hdcp_work = kzalloc(max_caps*sizeof(*hdcp_work), GFP_KERNEL); + struct hdcp_workqueue *hdcp_work; int i = 0; + hdcp_work = kcalloc(max_caps, sizeof(*hdcp_work), GFP_KERNEL); if (hdcp_work == NULL) + return NULL; + + hdcp_work->srm = kcalloc(PSP_HDCP_SRM_FIRST_GEN_MAX_SIZE, sizeof(*hdcp_work->srm), GFP_KERNEL); + + if (hdcp_work->srm == NULL) + goto fail_alloc_context; + + hdcp_work->srm_temp = kcalloc(PSP_HDCP_SRM_FIRST_GEN_MAX_SIZE, sizeof(*hdcp_work->srm_temp), GFP_KERNEL); + + if (hdcp_work->srm_temp == NULL) goto fail_alloc_context; hdcp_work->max_link = max_caps; for (i = 0; i < max_caps; i++) { - mutex_init(&hdcp_work[i].mutex); INIT_WORK(&hdcp_work[i].cpirq_work, event_cpirq); @@ -371,9 +539,17 @@ struct hdcp_workqueue *hdcp_create_workqueue(struct amdgpu_device *adev, struct cp_psp->funcs.update_stream_config = update_config; cp_psp->handle = hdcp_work; + /* File created at /sys/class/drm/card0/device/hdcp_srm*/ + hdcp_work[0].attr = data_attr; + + if (sysfs_create_bin_file(&adev->dev->kobj, &hdcp_work[0].attr)) + DRM_WARN("Failed to create device file hdcp_srm"); + return hdcp_work; fail_alloc_context: + kfree(hdcp_work->srm); + kfree(hdcp_work->srm_temp); kfree(hdcp_work); return NULL; diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.h index 331b50825510..5159b3a5e5b0 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.h @@ -53,6 +53,12 @@ struct hdcp_workqueue { enum mod_hdcp_encryption_status encryption_status; uint8_t max_link; + + uint8_t *srm; + uint8_t *srm_temp; + uint32_t srm_version; + uint32_t srm_size; + struct bin_attribute attr; }; void hdcp_update_display(struct hdcp_workqueue *hdcp_work, -- cgit From f4406d6fb23c72eb8ccf071db00fb06d9586bb5f Mon Sep 17 00:00:00 2001 From: Bhawanpreet Lakha Date: Wed, 4 Dec 2019 11:54:24 -0500 Subject: drm/amd/display: Load srm before enabling HDCP [Why] we need to load SRM before we start HDCP. Because for S3 case the sysfs call will be after we have already enabled HDCP, so we might not be using the latest SRM [How] Set srm before starting HDCP. Signed-off-by: Bhawanpreet Lakha Reviewed-by: Rodrigo Siqueira Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers/gpu/drm/amd/display') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.c index 221abee517ee..fe043b18bb21 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.c @@ -136,6 +136,13 @@ void hdcp_update_display(struct hdcp_workqueue *hdcp_work, hdcp_w->link.adjust.hdcp2.force_type = MOD_HDCP_FORCE_TYPE_0; if (enable_encryption) { + /* Explicitly set the saved SRM as sysfs call will be after we already enabled hdcp + * (s3 resume case) + */ + if (hdcp_work->srm_size > 0) + psp_set_srm(hdcp_work->hdcp.config.psp.handle, hdcp_work->srm, hdcp_work->srm_size, + &hdcp_work->srm_version); + display->adjust.disable = 0; if (content_type == DRM_MODE_HDCP_CONTENT_TYPE0) hdcp_w->link.adjust.hdcp2.force_type = MOD_HDCP_FORCE_TYPE_0; -- cgit From 1746d5a1d1a17dd389a00f335e2a1320feb4625b Mon Sep 17 00:00:00 2001 From: Bhawanpreet Lakha Date: Thu, 12 Dec 2019 16:38:38 -0500 Subject: drm/amd/display: call psp set/get interfaces Call the cmd ids for set/get srm according to the sysfs call v2: Use define for the magic number Signed-off-by: Bhawanpreet Lakha Reviewed-by: Rodrigo Siqueira Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.c | 50 +++++++++++++++++++++- 1 file changed, 49 insertions(+), 1 deletion(-) (limited to 'drivers/gpu/drm/amd/display') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.c index fe043b18bb21..c4fd148bf6e0 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.c @@ -30,6 +30,11 @@ #include #include "hdcp_psp.h" +/* + * If the SRM version being loaded is less than or equal to the + * currently loaded SRM, psp will return 0xFFFF as the version + */ +#define PSP_SRM_VERSION_MAX 0xFFFF static bool lp_write_i2c(void *handle, uint32_t address, const uint8_t *data, uint32_t size) @@ -71,11 +76,54 @@ lp_read_dpcd(void *handle, uint32_t address, uint8_t *data, uint32_t size) static uint8_t *psp_get_srm(struct psp_context *psp, uint32_t *srm_version, uint32_t *srm_size) { - return NULL; + + struct ta_hdcp_shared_memory *hdcp_cmd; + + if (!psp->hdcp_context.hdcp_initialized) { + DRM_WARN("Failed to get hdcp srm. HDCP TA is not initialized."); + return NULL; + } + + hdcp_cmd = (struct ta_hdcp_shared_memory *)psp->hdcp_context.hdcp_shared_buf; + memset(hdcp_cmd, 0, sizeof(struct ta_hdcp_shared_memory)); + + hdcp_cmd->cmd_id = TA_HDCP_COMMAND__HDCP_GET_SRM; + psp_hdcp_invoke(psp, hdcp_cmd->cmd_id); + + if (hdcp_cmd->hdcp_status != TA_HDCP_STATUS__SUCCESS) + return NULL; + + *srm_version = hdcp_cmd->out_msg.hdcp_get_srm.srm_version; + *srm_size = hdcp_cmd->out_msg.hdcp_get_srm.srm_buf_size; + + + return hdcp_cmd->out_msg.hdcp_get_srm.srm_buf; } static int psp_set_srm(struct psp_context *psp, uint8_t *srm, uint32_t srm_size, uint32_t *srm_version) { + + struct ta_hdcp_shared_memory *hdcp_cmd; + + if (!psp->hdcp_context.hdcp_initialized) { + DRM_WARN("Failed to get hdcp srm. HDCP TA is not initialized."); + return -EINVAL; + } + + hdcp_cmd = (struct ta_hdcp_shared_memory *)psp->hdcp_context.hdcp_shared_buf; + memset(hdcp_cmd, 0, sizeof(struct ta_hdcp_shared_memory)); + + memcpy(hdcp_cmd->in_msg.hdcp_set_srm.srm_buf, srm, srm_size); + hdcp_cmd->in_msg.hdcp_set_srm.srm_buf_size = srm_size; + hdcp_cmd->cmd_id = TA_HDCP_COMMAND__HDCP_SET_SRM; + + psp_hdcp_invoke(psp, hdcp_cmd->cmd_id); + + if (hdcp_cmd->hdcp_status != TA_HDCP_STATUS__SUCCESS || hdcp_cmd->out_msg.hdcp_set_srm.valid_signature != 1 || + hdcp_cmd->out_msg.hdcp_set_srm.srm_version == PSP_SRM_VERSION_MAX) + return -EINVAL; + + *srm_version = hdcp_cmd->out_msg.hdcp_set_srm.srm_version; return 0; } -- cgit From d4b8573ef05ad2007ae890e8e144e47c99f188d7 Mon Sep 17 00:00:00 2001 From: Wyatt Wood Date: Thu, 9 Jan 2020 14:29:13 -0500 Subject: drm/amd/display: Add set psr version message [Why] Must know psr version during runtime. [How] Add set psr version message structures. Signed-off-by: Wyatt Wood Reviewed-by: Nicholas Kazlauskas Acked-by: Bhawanpreet Lakha Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 6 +-- drivers/gpu/drm/amd/display/dc/dce/dmub_psr.c | 62 +++++++++++++++------- drivers/gpu/drm/amd/display/dc/dce/dmub_psr.h | 9 ++-- drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h | 10 ++-- .../gpu/drm/amd/display/dmub/inc/dmub_cmd_dal.h | 4 +- 5 files changed, 57 insertions(+), 34 deletions(-) (limited to 'drivers/gpu/drm/amd/display') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index a09119c10d7c..41184e593f85 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -2401,7 +2401,7 @@ bool dc_link_set_psr_allow_active(struct dc_link *link, bool allow_active, bool struct dmub_psr *psr = dc->res_pool->psr; if ((psr != NULL) && link->psr_feature_enabled) - psr->funcs->set_psr_enable(psr, allow_active); + psr->funcs->psr_enable(psr, allow_active); else if ((dmcu != NULL && dmcu->funcs->is_dmcu_initialized(dmcu)) && link->psr_feature_enabled) dmcu->funcs->set_psr_enable(dmcu, allow_active, wait); @@ -2417,7 +2417,7 @@ bool dc_link_get_psr_state(const struct dc_link *link, uint32_t *psr_state) struct dmub_psr *psr = dc->res_pool->psr; if (psr != NULL && link->psr_feature_enabled) - psr->funcs->get_psr_state(psr_state); + psr->funcs->psr_get_state(psr_state); else if (dmcu != NULL && link->psr_feature_enabled) dmcu->funcs->get_psr_state(dmcu, psr_state); @@ -2589,7 +2589,7 @@ bool dc_link_setup_psr(struct dc_link *link, psr_context->frame_delay = 0; if (psr) - link->psr_feature_enabled = psr->funcs->setup_psr(psr, link, psr_context); + link->psr_feature_enabled = psr->funcs->psr_copy_settings(psr, link, psr_context); else link->psr_feature_enabled = dmcu->funcs->setup_psr(dmcu, link, psr_context); diff --git a/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.c b/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.c index 225955ec6d39..bdf80b09277e 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.c @@ -36,16 +36,39 @@ /** * Get PSR state from firmware. */ -static void dmub_get_psr_state(uint32_t *psr_state) +static void dmub_psr_get_state(uint32_t *psr_state) { // Not yet implemented // Trigger GPINT interrupt from firmware } +static void dmub_psr_set_version(struct dmub_psr *dmub, struct dc_stream_state *stream) +{ + //stream->psr_version; + union dmub_rb_cmd cmd; + struct dc_context *dc = dmub->ctx; + + cmd.psr_set_version.header.type = DMUB_CMD__PSR; + cmd.psr_set_version.header.sub_type = DMUB_CMD__PSR_SET_VERSION; + + if (stream->psr_version == 0x0) + return; + else if (stream->psr_version == 0x1) + cmd.psr_set_version.psr_set_version_data.version = PSR_VERSION_1; + else if (stream->psr_version == 0x2) + cmd.psr_set_version.psr_set_version_data.version = PSR_VERSION_2; + + cmd.psr_enable.header.payload_bytes = sizeof(struct dmub_cmd_psr_set_version_data); + + dc_dmub_srv_cmd_queue(dc->dmub_srv, &cmd.psr_enable.header); + dc_dmub_srv_cmd_execute(dc->dmub_srv); + dc_dmub_srv_wait_idle(dc->dmub_srv); +} + /** * Enable/Disable PSR. */ -static void dmub_set_psr_enable(struct dmub_psr *dmub, bool enable) +static void dmub_psr_enable(struct dmub_psr *dmub, bool enable) { union dmub_rb_cmd cmd; struct dc_context *dc = dmub->ctx; @@ -67,13 +90,13 @@ static void dmub_set_psr_enable(struct dmub_psr *dmub, bool enable) /** * Set PSR level. */ -static void dmub_set_psr_level(struct dmub_psr *dmub, uint16_t psr_level) +static void dmub_psr_set_level(struct dmub_psr *dmub, uint16_t psr_level) { union dmub_rb_cmd cmd; uint32_t psr_state = 0; struct dc_context *dc = dmub->ctx; - dmub_get_psr_state(&psr_state); + dmub_psr_get_state(&psr_state); if (psr_state == 0) return; @@ -91,7 +114,7 @@ static void dmub_set_psr_level(struct dmub_psr *dmub, uint16_t psr_level) /** * Setup PSR by programming phy registers and sending psr hw context values to firmware. */ -static bool dmub_setup_psr(struct dmub_psr *dmub, +static bool dmub_psr_copy_settings(struct dmub_psr *dmub, struct dc_link *link, struct psr_context *psr_context) { @@ -104,18 +127,16 @@ static bool dmub_setup_psr(struct dmub_psr *dmub, for (int i = 0; i < MAX_PIPES; i++) { if (res_ctx && - res_ctx->pipe_ctx[i].stream && - res_ctx->pipe_ctx[i].stream->link && - res_ctx->pipe_ctx[i].stream->link == link && - res_ctx->pipe_ctx[i].stream->link->connector_signal == SIGNAL_TYPE_EDP) { + res_ctx->pipe_ctx[i].stream && + res_ctx->pipe_ctx[i].stream->link && + res_ctx->pipe_ctx[i].stream->link == link && + res_ctx->pipe_ctx[i].stream->link->connector_signal == SIGNAL_TYPE_EDP) { pipe_ctx = &res_ctx->pipe_ctx[i]; break; } } - if (!pipe_ctx || - !&pipe_ctx->plane_res || - !&pipe_ctx->stream_res) + if (!pipe_ctx || !&pipe_ctx->plane_res || !&pipe_ctx->stream_res) return false; // Program DP DPHY fast training registers @@ -161,13 +182,13 @@ static bool dmub_setup_psr(struct dmub_psr *dmub, copy_settings_data->hyst_lines = psr_context->hyst_lines; copy_settings_data->phy_type = psr_context->phyType; copy_settings_data->aux_repeat = psr_context->aux_repeats; - copy_settings_data->smu_optimizations_en = psr_context->allow_smu_optimizations; - copy_settings_data->skip_wait_for_pll_lock = psr_context->skipPsrWaitForPllLock; + copy_settings_data->smu_optimizations_en = psr_context->allow_smu_optimizations; + copy_settings_data->skip_wait_for_pll_lock = psr_context->skipPsrWaitForPllLock; copy_settings_data->frame_delay = psr_context->frame_delay; copy_settings_data->smu_phy_id = psr_context->smuPhyId; - copy_settings_data->num_of_controllers = psr_context->numberOfControllers; + copy_settings_data->num_of_controllers = psr_context->numberOfControllers; copy_settings_data->frame_cap_ind = psr_context->psrFrameCaptureIndicationReq; - copy_settings_data->phy_num = psr_context->frame_delay & 0x7; + copy_settings_data->phy_num = psr_context->frame_delay & 0x7; copy_settings_data->link_rate = psr_context->frame_delay & 0xF; dc_dmub_srv_cmd_queue(dc->dmub_srv, &cmd.psr_copy_settings.header); @@ -178,10 +199,11 @@ static bool dmub_setup_psr(struct dmub_psr *dmub, } static const struct dmub_psr_funcs psr_funcs = { - .set_psr_enable = dmub_set_psr_enable, - .setup_psr = dmub_setup_psr, - .get_psr_state = dmub_get_psr_state, - .set_psr_level = dmub_set_psr_level, + .psr_set_version = dmub_psr_set_version, + .psr_copy_settings = dmub_psr_copy_settings, + .psr_enable = dmub_psr_enable, + .psr_get_state = dmub_psr_get_state, + .psr_set_level = dmub_psr_set_level, }; /** diff --git a/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.h b/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.h index 229958de3035..4fe8b53d9551 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.h @@ -34,10 +34,11 @@ struct dmub_psr { }; struct dmub_psr_funcs { - void (*set_psr_enable)(struct dmub_psr *dmub, bool enable); - bool (*setup_psr)(struct dmub_psr *dmub, struct dc_link *link, struct psr_context *psr_context); - void (*get_psr_state)(uint32_t *psr_state); - void (*set_psr_level)(struct dmub_psr *dmub, uint16_t psr_level); + void (*psr_set_version)(struct dmub_psr *dmub, struct dc_stream_state *stream); + bool (*psr_copy_settings)(struct dmub_psr *dmub, struct dc_link *link, struct psr_context *psr_context); + void (*psr_enable)(struct dmub_psr *dmub, bool enable); + void (*psr_get_state)(uint32_t *psr_state); + void (*psr_set_level)(struct dmub_psr *dmub, uint16_t psr_level); }; struct dmub_psr *dmub_psr_create(struct dc_context *ctx); diff --git a/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h b/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h index cd9532b4f14d..8f518e7d8b4e 100644 --- a/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h +++ b/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h @@ -257,13 +257,13 @@ struct dmub_rb_cmd_psr_enable { struct dmub_cmd_header header; }; -struct dmub_cmd_psr_setup_data { +struct dmub_cmd_psr_set_version_data { enum psr_version version; // PSR version 1 or 2 }; -struct dmub_rb_cmd_psr_setup { +struct dmub_rb_cmd_psr_set_version { struct dmub_cmd_header header; - struct dmub_cmd_psr_setup_data psr_setup_data; + struct dmub_cmd_psr_set_version_data psr_set_version_data; }; union dmub_rb_cmd { @@ -277,11 +277,11 @@ union dmub_rb_cmd { struct dmub_rb_cmd_enable_disp_power_gating enable_disp_power_gating; struct dmub_rb_cmd_dpphy_init dpphy_init; struct dmub_rb_cmd_dig1_transmitter_control dig1_transmitter_control; - struct dmub_rb_cmd_psr_enable psr_enable; + struct dmub_rb_cmd_psr_set_version psr_set_version; struct dmub_rb_cmd_psr_copy_settings psr_copy_settings; + struct dmub_rb_cmd_psr_enable psr_enable; struct dmub_rb_cmd_psr_set_level psr_set_level; struct dmub_rb_cmd_PLAT_54186_wa PLAT_54186_wa; - struct dmub_rb_cmd_psr_setup psr_setup; }; #pragma pack(pop) diff --git a/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd_dal.h b/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd_dal.h index 7b69eb37f762..ce793f47f234 100644 --- a/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd_dal.h +++ b/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd_dal.h @@ -32,7 +32,7 @@ */ enum dmub_cmd_psr_type { - DMUB_CMD__PSR_SETUP = 0, + DMUB_CMD__PSR_SET_VERSION = 0, DMUB_CMD__PSR_COPY_SETTINGS = 1, DMUB_CMD__PSR_ENABLE = 2, DMUB_CMD__PSR_DISABLE = 3, @@ -42,7 +42,7 @@ enum dmub_cmd_psr_type { enum psr_version { PSR_VERSION_1 = 0x10, // PSR Version 1 PSR_VERSION_2 = 0x20, // PSR Version 2, includes selective update - PSR_VERSION_2_Y_COORD = 0x21, // PSR Version 2, includes Y-coordinate support for SU + PSR_VERSION_2_1 = 0x21, // PSR Version 2, includes Y-coordinate support for SU }; #endif /* _DMUB_CMD_DAL_H_ */ -- cgit From b32827384cc5fd1151da6193d596ac1036828da5 Mon Sep 17 00:00:00 2001 From: George Shen Date: Tue, 14 Jan 2020 17:11:15 -0500 Subject: drm/amd/display: Move USB-C workaround to after parameter variables are set [Why] The call to dp_enable_link_phy are using default/invalid values for clock id and link settings. [How] Move workaround code to after its parameter variables are determined. Signed-off-by: George Shen Reviewed-by: Tony Cheng Acked-by: Bhawanpreet Lakha Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) (limited to 'drivers/gpu/drm/amd/display') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c index cb731c1d30b1..8ff0f5b7104b 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c @@ -1892,6 +1892,16 @@ bool dp_verify_link_cap( /* disable PHY done possible by BIOS, will be done by driver itself */ dp_disable_link_phy(link, link->connector_signal); + dp_cs_id = get_clock_source_id(link); + + /* link training starts with the maximum common settings + * supported by both sink and ASIC. + */ + initial_link_settings = get_common_supported_link_settings( + *known_limit_link_setting, + max_link_cap); + cur_link_setting = initial_link_settings; + /* Temporary Renoir-specific workaround for SWDEV-215184; * PHY will sometimes be in bad state on hotplugging display from certain USB-C dongle, * so add extra cycle of enabling and disabling the PHY before first link training. @@ -1902,15 +1912,6 @@ bool dp_verify_link_cap( dp_disable_link_phy(link, link->connector_signal); } - dp_cs_id = get_clock_source_id(link); - - /* link training starts with the maximum common settings - * supported by both sink and ASIC. - */ - initial_link_settings = get_common_supported_link_settings( - *known_limit_link_setting, - max_link_cap); - cur_link_setting = initial_link_settings; do { skip_video_pattern = true; -- cgit From e2d533eceb1feb0b8b965c3ff11184921532a28e Mon Sep 17 00:00:00 2001 From: Joseph Gravenor Date: Wed, 15 Jan 2020 13:27:06 -0500 Subject: drm/amd/display: remove invalid dc_is_hw_initialized function [why/how] We found out that the register we read actually gets reset by SMU after we loose power, meaning this always returns true Signed-off-by: Joseph Gravenor Reviewed-by: Eric Yang Acked-by: Bhawanpreet Lakha Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 6 ------ drivers/gpu/drm/amd/display/dc/dc.h | 1 - 2 files changed, 7 deletions(-) (limited to 'drivers/gpu/drm/amd/display') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 04441dbcba76..073172e53b5b 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1318,12 +1318,6 @@ bool dc_commit_state(struct dc *dc, struct dc_state *context) return (result == DC_OK); } -bool dc_is_hw_initialized(struct dc *dc) -{ - struct dc_bios *dcb = dc->ctx->dc_bios; - return dcb->funcs->is_accelerated_mode(dcb); -} - bool dc_post_update_surfaces_to_stream(struct dc *dc) { int i; diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 8ff25b5dd2f6..e8d126890d7e 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -1075,7 +1075,6 @@ unsigned int dc_get_current_backlight_pwm(struct dc *dc); unsigned int dc_get_target_backlight_pwm(struct dc *dc); bool dc_is_dmcu_initialized(struct dc *dc); -bool dc_is_hw_initialized(struct dc *dc); enum dc_status dc_set_clock(struct dc *dc, enum dc_clock_type clock_type, uint32_t clk_khz, uint32_t stepping); void dc_get_clock(struct dc *dc, enum dc_clock_type clock_type, struct dc_clock_config *clock_cfg); -- cgit From 2286d2f9e58cb0ae7b9db97106ce73613ab33e5e Mon Sep 17 00:00:00 2001 From: Roman Li Date: Tue, 14 Jan 2020 13:56:08 -0500 Subject: drm/amd/display: Fix psr static frames calculation [Why] Driver crash with psr feature enabled due to divide-by-zero error. This is a regression after rework to calculate static screen frame number entry time. [How] Correct order of operations to avoid divide-by-zero. Signed-off-by: Roman Li Reviewed-by: Zhan Liu Acked-by: Bhawanpreet Lakha Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers/gpu/drm/amd/display') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index d0ddbc9df264..bd798b6bdf0f 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -8408,7 +8408,6 @@ bool amdgpu_dm_psr_enable(struct dc_stream_state *stream) /* Calculate number of static frames before generating interrupt to * enter PSR. */ - unsigned int frame_time_microsec = 1000000 / vsync_rate_hz; // Init fail safe of 2 frames static unsigned int num_frames_static = 2; @@ -8423,8 +8422,10 @@ bool amdgpu_dm_psr_enable(struct dc_stream_state *stream) * Calculate number of frames such that at least 30 ms of time has * passed. */ - if (vsync_rate_hz != 0) + if (vsync_rate_hz != 0) { + unsigned int frame_time_microsec = 1000000 / vsync_rate_hz; num_frames_static = (30000 / frame_time_microsec) + 1; + } params.triggers.cursor_update = true; params.triggers.overlay_update = true; -- cgit From 0b464c857cc0e143f58938a1f506ab159837bcb3 Mon Sep 17 00:00:00 2001 From: Sung Lee Date: Wed, 15 Jan 2020 11:55:06 -0500 Subject: drm/amd/display: Do not set optimized_require to false after plane disable [WHY] The optimized_require flag is needed to set watermarks and clocks lower in certain conditions. This flag is set to true and then set to false while programming front end in dcn20. [HOW] Do not set the flag to false while disabling plane. Signed-off-by: Sung Lee Reviewed-by: Tony Cheng Acked-by: Bhawanpreet Lakha Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/gpu/drm/amd/display') diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c index cfbbaffa8654..a444fed94184 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c @@ -572,7 +572,6 @@ void dcn20_plane_atomic_disable(struct dc *dc, struct pipe_ctx *pipe_ctx) dpp->funcs->dpp_dppclk_control(dpp, false, false); hubp->power_gated = true; - dc->optimized_required = false; /* We're powering off, no need to optimize */ hws->funcs.plane_atomic_power_down(dc, pipe_ctx->plane_res.dpp, -- cgit From bbf5f6c3f83bedd71006473849138a446ad4d9a3 Mon Sep 17 00:00:00 2001 From: Anthony Koo Date: Tue, 14 Jan 2020 16:23:31 -0500 Subject: drm/amd/display: Split program front end part that occur outside lock [Why] Eventually want to lock at a higher level in stack. To do this, we need to be able to isolate the parts that need to be done after pipe unlock. [How] Split out programming that is done post unlock. Signed-off-by: Anthony Koo Reviewed-by: Aric Cyr Acked-by: Bhawanpreet Lakha Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 24 ++++++++++--- .../amd/display/dc/dce110/dce110_hw_sequencer.c | 6 ++++ .../drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 39 ++++++++++++++++++---- .../drm/amd/display/dc/dcn10/dcn10_hw_sequencer.h | 3 ++ drivers/gpu/drm/amd/display/dc/dcn10/dcn10_init.c | 1 + drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c | 11 +++++- drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.h | 3 ++ drivers/gpu/drm/amd/display/dc/dcn20/dcn20_init.c | 1 + drivers/gpu/drm/amd/display/dc/dcn21/dcn21_init.c | 1 + drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h | 2 ++ 10 files changed, 79 insertions(+), 12 deletions(-) (limited to 'drivers/gpu/drm/amd/display') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 073172e53b5b..738ba91220df 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -786,11 +786,15 @@ static void disable_dangling_plane(struct dc *dc, struct dc_state *context) if (should_disable && old_stream) { dc_rem_all_planes_for_stream(dc, old_stream, dangling_context); disable_all_writeback_pipes_for_stream(dc, old_stream, dangling_context); - if (dc->hwss.apply_ctx_for_surface) + if (dc->hwss.apply_ctx_for_surface) { dc->hwss.apply_ctx_for_surface(dc, old_stream, 0, dangling_context); + dc->hwss.post_unlock_program_front_end(dc, dangling_context); + } + if (dc->hwss.program_front_end_for_ctx) { + dc->hwss.program_front_end_for_ctx(dc, dangling_context); + dc->hwss.post_unlock_program_front_end(dc, dangling_context); + } } - if (dc->hwss.program_front_end_for_ctx) - dc->hwss.program_front_end_for_ctx(dc, dangling_context); } current_ctx = dc->current_state; @@ -1219,6 +1223,7 @@ static enum dc_status dc_commit_state_no_check(struct dc *dc, struct dc_state *c dc, context->streams[i], context->stream_status[i].plane_count, context); /* use new pipe config in new context */ + dc->hwss.post_unlock_program_front_end(dc, context); } /* Program hardware */ @@ -1238,19 +1243,24 @@ static enum dc_status dc_commit_state_no_check(struct dc *dc, struct dc_state *c } /* Program all planes within new context*/ - if (dc->hwss.program_front_end_for_ctx) + if (dc->hwss.program_front_end_for_ctx) { dc->hwss.program_front_end_for_ctx(dc, context); + dc->hwss.post_unlock_program_front_end(dc, context); + } + for (i = 0; i < context->stream_count; i++) { const struct dc_link *link = context->streams[i]->link; if (!context->streams[i]->mode_changed) continue; - if (dc->hwss.apply_ctx_for_surface) + if (dc->hwss.apply_ctx_for_surface) { dc->hwss.apply_ctx_for_surface( dc, context->streams[i], context->stream_status[i].plane_count, context); + dc->hwss.post_unlock_program_front_end(dc, context); + } /* * enable stereo @@ -2183,6 +2193,7 @@ static void commit_planes_for_stream(struct dc *dc, if (dc->hwss.program_front_end_for_ctx) dc->hwss.program_front_end_for_ctx(dc, context); + dc->hwss.post_unlock_program_front_end(dc, context); return; } @@ -2315,6 +2326,9 @@ static void commit_planes_for_stream(struct dc *dc, dc->hwss.pipe_control_lock(dc, top_pipe_to_program, false); } + if (update_type != UPDATE_TYPE_FAST) + dc->hwss.post_unlock_program_front_end(dc, context); + // Fire manual trigger only when bottom plane is flipped for (j = 0; j < dc->res_pool->pipe_count; j++) { struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j]; diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 5b689273ff44..a961b94aefd9 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -2621,6 +2621,11 @@ static void dce110_apply_ctx_for_surface( enable_fbc(dc, context); } +static void dce110_post_unlock_program_front_end( + struct dc *dc, + struct dc_state *context) +{ +} static void dce110_power_down_fe(struct dc *dc, struct pipe_ctx *pipe_ctx) { struct dce_hwseq *hws = dc->hwseq; @@ -2722,6 +2727,7 @@ static const struct hw_sequencer_funcs dce110_funcs = { .init_hw = init_hw, .apply_ctx_to_hw = dce110_apply_ctx_to_hw, .apply_ctx_for_surface = dce110_apply_ctx_for_surface, + .post_unlock_program_front_end = dce110_post_unlock_program_front_end, .update_plane_addr = update_plane_addr, .update_pending_status = dce110_update_pending_status, .enable_accelerated_mode = dce110_enable_accelerated_mode, diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 1008ac8a0f2a..a9a5a13d5edf 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -2512,7 +2512,6 @@ void dcn10_apply_ctx_for_surface( int i; struct timing_generator *tg; uint32_t underflow_check_delay_us; - bool removed_pipe[4] = { false }; bool interdependent_update = false; struct pipe_ctx *top_pipe_to_program = dcn10_find_top_pipe_for_stream(dc, context, stream); @@ -2552,6 +2551,9 @@ void dcn10_apply_ctx_for_surface( struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; struct pipe_ctx *old_pipe_ctx = &dc->current_state->res_ctx.pipe_ctx[i]; + + pipe_ctx->update_flags.raw = 0; + /* * Powergate reused pipes that are not powergated * fairly hacky right now, using opp_id as indicator @@ -2571,7 +2573,7 @@ void dcn10_apply_ctx_for_surface( old_pipe_ctx->stream_res.tg == tg) { hws->funcs.plane_atomic_disconnect(dc, old_pipe_ctx); - removed_pipe[i] = true; + pipe_ctx->update_flags.bits.disable = 1; DC_LOG_DC("Reset mpcc for pipe %d\n", old_pipe_ctx->pipe_idx); @@ -2602,16 +2604,41 @@ void dcn10_apply_ctx_for_surface( dcn10_lock_all_pipes(dc, context, false); else dcn10_pipe_control_lock(dc, top_pipe_to_program, false); +} + +void dcn10_post_unlock_program_front_end( + struct dc *dc, + struct dc_state *context) +{ + int i, j; + + DC_LOGGER_INIT(dc->ctx->logger); - if (num_planes == 0) - false_optc_underflow_wa(dc, stream, tg); + for (i = 0; i < dc->res_pool->pipe_count; i++) { + struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; + + if (!pipe_ctx->top_pipe && + !pipe_ctx->prev_odm_pipe && + pipe_ctx->stream) { + struct dc_stream_status *stream_status = NULL; + struct timing_generator *tg = pipe_ctx->stream_res.tg; + + for (j = 0; j < context->stream_count; j++) { + if (pipe_ctx->stream == context->streams[j]) + stream_status = &context->stream_status[j]; + } + + if (context->stream_status[i].plane_count == 0) + false_optc_underflow_wa(dc, pipe_ctx->stream, tg); + } + } for (i = 0; i < dc->res_pool->pipe_count; i++) - if (removed_pipe[i]) + if (context->res_ctx.pipe_ctx[i].update_flags.bits.disable) dc->hwss.disable_plane(dc, &dc->current_state->res_ctx.pipe_ctx[i]); for (i = 0; i < dc->res_pool->pipe_count; i++) - if (removed_pipe[i]) { + if (context->res_ctx.pipe_ctx[i].update_flags.bits.disable) { dc->hwss.optimize_bandwidth(dc, context); break; } diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.h index 4d20f6586bb5..b523f0b8dc23 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.h @@ -75,6 +75,9 @@ void dcn10_apply_ctx_for_surface( const struct dc_stream_state *stream, int num_planes, struct dc_state *context); +void dcn10_post_unlock_program_front_end( + struct dc *dc, + struct dc_state *context); void dcn10_hubp_pg_control( struct dce_hwseq *hws, unsigned int hubp_inst, diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_init.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_init.c index e7e5352ec424..681db997a532 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_init.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_init.c @@ -32,6 +32,7 @@ static const struct hw_sequencer_funcs dcn10_funcs = { .init_hw = dcn10_init_hw, .apply_ctx_to_hw = dce110_apply_ctx_to_hw, .apply_ctx_for_surface = dcn10_apply_ctx_for_surface, + .post_unlock_program_front_end = dcn10_post_unlock_program_front_end, .update_plane_addr = dcn10_update_plane_addr, .update_dchub = dcn10_update_dchub, .update_pending_status = dcn10_update_pending_status, diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c index a444fed94184..f36c4d1b7c30 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c @@ -1551,7 +1551,6 @@ void dcn20_program_front_end_for_ctx( struct dc *dc, struct dc_state *context) { - const unsigned int TIMEOUT_FOR_PIPE_ENABLE_MS = 100; int i; struct dce_hwseq *hws = dc->hwseq; bool pipe_locked[MAX_PIPES] = {false}; @@ -1626,6 +1625,16 @@ void dcn20_program_front_end_for_ctx( if (!pipe_ctx->update_flags.bits.enable) dc->hwss.pipe_control_lock(dc, &dc->current_state->res_ctx.pipe_ctx[i], false); } +} + +void dcn20_post_unlock_program_front_end( + struct dc *dc, + struct dc_state *context) +{ + int i; + const unsigned int TIMEOUT_FOR_PIPE_ENABLE_MS = 100; + + DC_LOGGER_INIT(dc->ctx->logger); for (i = 0; i < dc->res_pool->pipe_count; i++) if (context->res_ctx.pipe_ctx[i].update_flags.bits.disable) diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.h b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.h index 02c9be5ebd47..80f192b8b3a2 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.h +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.h @@ -35,6 +35,9 @@ bool dcn20_set_shaper_3dlut( void dcn20_program_front_end_for_ctx( struct dc *dc, struct dc_state *context); +void dcn20_post_unlock_program_front_end( + struct dc *dc, + struct dc_state *context); void dcn20_update_plane_addr(const struct dc *dc, struct pipe_ctx *pipe_ctx); void dcn20_update_mpcc(struct dc *dc, struct pipe_ctx *pipe_ctx); bool dcn20_set_input_transfer_func(struct dc *dc, struct pipe_ctx *pipe_ctx, diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_init.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_init.c index d51e02fdab4d..cb0cb999251e 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_init.c +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_init.c @@ -33,6 +33,7 @@ static const struct hw_sequencer_funcs dcn20_funcs = { .apply_ctx_to_hw = dce110_apply_ctx_to_hw, .apply_ctx_for_surface = NULL, .program_front_end_for_ctx = dcn20_program_front_end_for_ctx, + .post_unlock_program_front_end = dcn20_post_unlock_program_front_end, .update_plane_addr = dcn20_update_plane_addr, .update_dchub = dcn10_update_dchub, .update_pending_status = dcn10_update_pending_status, diff --git a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_init.c b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_init.c index 4861aa5c59ae..4963a540948d 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_init.c +++ b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_init.c @@ -34,6 +34,7 @@ static const struct hw_sequencer_funcs dcn21_funcs = { .apply_ctx_to_hw = dce110_apply_ctx_to_hw, .apply_ctx_for_surface = NULL, .program_front_end_for_ctx = dcn20_program_front_end_for_ctx, + .post_unlock_program_front_end = dcn20_post_unlock_program_front_end, .update_plane_addr = dcn20_update_plane_addr, .update_dchub = dcn10_update_dchub, .update_pending_status = dcn10_update_pending_status, diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h index 209118f9f193..63919866ba38 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h @@ -66,6 +66,8 @@ struct hw_sequencer_funcs { int num_planes, struct dc_state *context); void (*program_front_end_for_ctx)(struct dc *dc, struct dc_state *context); + void (*post_unlock_program_front_end)(struct dc *dc, + struct dc_state *context); void (*update_plane_addr)(const struct dc *dc, struct pipe_ctx *pipe_ctx); void (*update_dchub)(struct dce_hwseq *hws, -- cgit From acdac228c4d1b9ff8ac778835719d3381c198aad Mon Sep 17 00:00:00 2001 From: Anthony Koo Date: Tue, 14 Jan 2020 17:02:09 -0500 Subject: drm/amd/display: Indicate dsc updates explicitly [Why] DSC updates only set type to FULL UPDATE, but doesn't flag the change [How] Add DSC flag update flag Signed-off-by: Anthony Koo Reviewed-by: Aric Cyr Acked-by: Bhawanpreet Lakha Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 19 ++++++++++++------- drivers/gpu/drm/amd/display/dc/dc_stream.h | 1 + 2 files changed, 13 insertions(+), 7 deletions(-) (limited to 'drivers/gpu/drm/amd/display') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 738ba91220df..c9c7cf00976f 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1738,14 +1738,15 @@ static enum surface_update_type check_update_surfaces_for_stream( if (stream_update->wb_update) su_flags->bits.wb_update = 1; + + if (stream_update->dsc_config) + su_flags->bits.dsc_changed = 1; + if (su_flags->raw != 0) overall_type = UPDATE_TYPE_FULL; if (stream_update->output_csc_transform || stream_update->output_color_space) su_flags->bits.out_csc = 1; - - if (stream_update->dsc_config) - overall_type = UPDATE_TYPE_FULL; } for (i = 0 ; i < surface_count; i++) { @@ -1780,8 +1781,11 @@ enum surface_update_type dc_check_update_surfaces_for_stream( type = check_update_surfaces_for_stream(dc, updates, surface_count, stream_update, stream_status); if (type == UPDATE_TYPE_FULL) { - if (stream_update) + if (stream_update) { + uint32_t dsc_changed = stream_update->stream->update_flags.bits.dsc_changed; stream_update->stream->update_flags.raw = 0xFFFFFFFF; + stream_update->stream->update_flags.bits.dsc_changed = dsc_changed; + } for (i = 0; i < surface_count; i++) updates[i].surface->update_flags.raw = 0xFFFFFFFF; } @@ -2097,14 +2101,15 @@ static void commit_planes_do_stream_update(struct dc *dc, } } + /* Full fe update*/ + if (update_type == UPDATE_TYPE_FAST) + continue; + if (stream_update->dsc_config && dc->hwss.pipe_control_lock_global) { dc->hwss.pipe_control_lock_global(dc, pipe_ctx, true); dp_update_dsc_config(pipe_ctx); dc->hwss.pipe_control_lock_global(dc, pipe_ctx, false); } - /* Full fe update*/ - if (update_type == UPDATE_TYPE_FAST) - continue; if (stream_update->dpms_off) { dc->hwss.pipe_control_lock(dc, pipe_ctx, true); diff --git a/drivers/gpu/drm/amd/display/dc/dc_stream.h b/drivers/gpu/drm/amd/display/dc/dc_stream.h index 92096de79dec..a5c7ef47b8d3 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_stream.h +++ b/drivers/gpu/drm/amd/display/dc/dc_stream.h @@ -118,6 +118,7 @@ union stream_update_flags { uint32_t dpms_off:1; uint32_t gamut_remap:1; uint32_t wb_update:1; + uint32_t dsc_changed : 1; } bits; uint32_t raw; -- cgit From 47b0c91f29f85282f1ad777d4059ce4e0c6aeb12 Mon Sep 17 00:00:00 2001 From: Eric Bernstein Date: Wed, 15 Jan 2020 14:41:23 -0500 Subject: drm/amd/display: Fix various issues found by compiler warning as errors [Why] Diagnostics team reported various issues found when enabling warnings as errors [How] Fix implicit conversions Signed-off-by: Eric Bernstein Reviewed-by: Aric Cyr Acked-by: Bhawanpreet Lakha Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c | 2 +- drivers/gpu/drm/amd/display/dc/dml/display_mode_structs.h | 2 +- drivers/gpu/drm/amd/display/dc/inc/hw/dwb.h | 3 +-- 3 files changed, 3 insertions(+), 4 deletions(-) (limited to 'drivers/gpu/drm/amd/display') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c index 8ff0f5b7104b..07b9aa1d01af 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c @@ -3681,7 +3681,7 @@ static void set_crtc_test_pattern(struct dc_link *link, struct pipe_ctx *odm_pipe; enum controller_dp_color_space controller_color_space; int opp_cnt = 1; - int count; + uint16_t count = 0; switch (test_pattern_color_space) { case DP_TEST_PATTERN_COLOR_SPACE_RGB: diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_mode_structs.h b/drivers/gpu/drm/amd/display/dc/dml/display_mode_structs.h index 658f81e757e9..1f5446321112 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/display_mode_structs.h +++ b/drivers/gpu/drm/amd/display/dc/dml/display_mode_structs.h @@ -189,7 +189,7 @@ struct _vcs_dpi_ip_params_st { unsigned int min_vblank_lines; unsigned int dppclk_delay_subtotal; unsigned int dispclk_delay_subtotal; - unsigned int dcfclk_cstate_latency; + double dcfclk_cstate_latency; unsigned int dppclk_delay_scl; unsigned int dppclk_delay_scl_lb_only; unsigned int dppclk_delay_cnvc_formatter; diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/dwb.h b/drivers/gpu/drm/amd/display/dc/inc/hw/dwb.h index 459f95f52486..f30ab4916242 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/dwb.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/dwb.h @@ -25,16 +25,15 @@ #ifndef __DC_DWBC_H__ #define __DC_DWBC_H__ +#include "dal_types.h" #include "dc_hw_types.h" - #define DWB_SW_V2 1 #define DWB_MCIF_BUF_COUNT 4 /* forward declaration of mcif_wb struct */ struct mcif_wb; -enum dce_version; enum dwb_sw_version { dwb_ver_1_0 = 1, -- cgit From fbbd3f8f6b8fd0165ed95cc0236cd482175a0403 Mon Sep 17 00:00:00 2001 From: Nicholas Kazlauskas Date: Wed, 15 Jan 2020 15:17:29 -0500 Subject: drm/amd/display: Add GPINT handler interface [Why] The General Purpose Interrupt is used on the DMCUB to pass lightweight commands via a register to the DMCUB. This is limited to 32-bit command and 32-bit response. This will be used for shutting down the firmware in a clean manner. [How] Add the command IDs and the data register to correctly format the commands. Add the interface functions to dmub_srv for sending and receiving the commands. Signed-off-by: Nicholas Kazlauskas Reviewed-by: Tony Cheng Acked-by: Bhawanpreet Lakha Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dmub/inc/dmub_gpint_cmd.h | 68 ++++++++++++++++++++++ drivers/gpu/drm/amd/display/dmub/inc/dmub_srv.h | 48 +++++++++++++++ drivers/gpu/drm/amd/display/dmub/src/dmub_dcn20.c | 22 +++++++ drivers/gpu/drm/amd/display/dmub/src/dmub_dcn20.h | 9 +++ drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c | 50 ++++++++++++++++ 5 files changed, 197 insertions(+) create mode 100644 drivers/gpu/drm/amd/display/dmub/inc/dmub_gpint_cmd.h (limited to 'drivers/gpu/drm/amd/display') diff --git a/drivers/gpu/drm/amd/display/dmub/inc/dmub_gpint_cmd.h b/drivers/gpu/drm/amd/display/dmub/inc/dmub_gpint_cmd.h new file mode 100644 index 000000000000..5398ed6b35d1 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dmub/inc/dmub_gpint_cmd.h @@ -0,0 +1,68 @@ +/* + * Copyright 2019 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef _DMUB_GPINT_CMD_H_ +#define _DMUB_GPINT_CMD_H_ + +#include "dmub_types.h" + +/** + * The register format for sending a command via the GPINT. + */ +union dmub_gpint_data_register { + struct { + uint32_t param : 16; + uint32_t command_code : 12; + uint32_t status : 4; + } bits; + uint32_t all; +}; + +/** + * The shifts and masks below may alternatively be used to format and read + * the command register bits. + */ + +#define DMUB_GPINT_DATA_PARAM_MASK 0xFFFF +#define DMUB_GPINT_DATA_PARAM_SHIFT 0 + +#define DMUB_GPINT_DATA_COMMAND_CODE_MASK 0xFFF +#define DMUB_GPINT_DATA_COMMAND_CODE_SHIFT 16 + +#define DMUB_GPINT_DATA_STATUS_MASK 0xF +#define DMUB_GPINT_DATA_STATUS_SHIFT 28 + +/* + * Command IDs should be treated as stable ABI. + * Do not reuse or modify IDs. + */ + +enum dmub_gpint_command { + DMUB_GPINT__INVALID_COMMAND = 0, + DMUB_GPINT__GET_FW_VERSION = 1, + DMUB_GPINT__STOP_FW = 2, +}; + +#endif /* _DMUB_GPINT_CMD_H_ */ diff --git a/drivers/gpu/drm/amd/display/dmub/inc/dmub_srv.h b/drivers/gpu/drm/amd/display/dmub/inc/dmub_srv.h index f8917594036a..e619fa9cf53a 100644 --- a/drivers/gpu/drm/amd/display/dmub/inc/dmub_srv.h +++ b/drivers/gpu/drm/amd/display/dmub/inc/dmub_srv.h @@ -66,6 +66,7 @@ #include "dmub_types.h" #include "dmub_cmd.h" +#include "dmub_gpint_cmd.h" #include "dmub_rb.h" #if defined(__cplusplus) @@ -262,6 +263,14 @@ struct dmub_srv_hw_funcs { bool (*is_phy_init)(struct dmub_srv *dmub); bool (*is_auto_load_done)(struct dmub_srv *dmub); + + void (*set_gpint)(struct dmub_srv *dmub, + union dmub_gpint_data_register reg); + + bool (*is_gpint_acked)(struct dmub_srv *dmub, + union dmub_gpint_data_register reg); + + uint32_t (*get_gpint_response)(struct dmub_srv *dmub); }; /** @@ -516,6 +525,45 @@ enum dmub_status dmub_srv_wait_for_phy_init(struct dmub_srv *dmub, enum dmub_status dmub_srv_wait_for_idle(struct dmub_srv *dmub, uint32_t timeout_us); +/** + * dmub_srv_send_gpint_command() - Sends a GPINT based command. + * @dmub: the dmub service + * @command_code: the command code to send + * @param: the command parameter to send + * @timeout_us: the maximum number of microseconds to wait + * + * Sends a command via the general purpose interrupt (GPINT). + * Waits for the number of microseconds specified by timeout_us + * for the command ACK before returning. + * + * Can be called after software initialization. + * + * Return: + * DMUB_STATUS_OK - success + * DMUB_STATUS_TIMEOUT - wait for ACK timed out + * DMUB_STATUS_INVALID - unspecified error + */ +enum dmub_status +dmub_srv_send_gpint_command(struct dmub_srv *dmub, + enum dmub_gpint_command command_code, + uint16_t param, uint32_t timeout_us); + +/** + * dmub_srv_get_gpint_response() - Queries the GPINT response. + * @dmub: the dmub service + * @response: the response for the last GPINT + * + * Returns the response code for the last GPINT interrupt. + * + * Can be called after software initialization. + * + * Return: + * DMUB_STATUS_OK - success + * DMUB_STATUS_INVALID - unspecified error + */ +enum dmub_status dmub_srv_get_gpint_response(struct dmub_srv *dmub, + uint32_t *response); + #if defined(__cplusplus) } #endif diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn20.c b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn20.c index b2ca8e0dbac9..7c1604c2221c 100644 --- a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn20.c +++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn20.c @@ -217,3 +217,25 @@ bool dmub_dcn20_is_supported(struct dmub_srv *dmub) return supported; } + +void dmub_dcn20_set_gpint(struct dmub_srv *dmub, + union dmub_gpint_data_register reg) +{ + REG_WRITE(DMCUB_GPINT_DATAIN1, reg.all); +} + +bool dmub_dcn20_is_gpint_acked(struct dmub_srv *dmub, + union dmub_gpint_data_register reg) +{ + union dmub_gpint_data_register test; + + reg.bits.status = 0; + test.all = REG_READ(DMCUB_GPINT_DATAIN1); + + return test.all == reg.all; +} + +uint32_t dmub_dcn20_get_gpint_response(struct dmub_srv *dmub) +{ + return REG_READ(DMCUB_SCRATCH7); +} diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn20.h b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn20.h index 04b0fa13153d..7f046c73927e 100644 --- a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn20.h +++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn20.h @@ -91,6 +91,7 @@ struct dmub_srv; DMUB_SR(DMCUB_SCRATCH13) \ DMUB_SR(DMCUB_SCRATCH14) \ DMUB_SR(DMCUB_SCRATCH15) \ + DMUB_SR(DMCUB_GPINT_DATAIN1) \ DMUB_SR(CC_DC_PIPE_DIS) \ DMUB_SR(MMHUBBUB_SOFT_RESET) \ DMUB_SR(DCN_VM_FB_LOCATION_BASE) \ @@ -183,4 +184,12 @@ bool dmub_dcn20_is_hw_init(struct dmub_srv *dmub); bool dmub_dcn20_is_supported(struct dmub_srv *dmub); +void dmub_dcn20_set_gpint(struct dmub_srv *dmub, + union dmub_gpint_data_register reg); + +bool dmub_dcn20_is_gpint_acked(struct dmub_srv *dmub, + union dmub_gpint_data_register reg); + +uint32_t dmub_dcn20_get_gpint_response(struct dmub_srv *dmub); + #endif /* _DMUB_DCN20_H_ */ diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c b/drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c index 85a518bf8a76..45be185ef312 100644 --- a/drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c +++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c @@ -126,6 +126,9 @@ static bool dmub_srv_hw_setup(struct dmub_srv *dmub, enum dmub_asic asic) funcs->set_inbox1_wptr = dmub_dcn20_set_inbox1_wptr; funcs->is_supported = dmub_dcn20_is_supported; funcs->is_hw_init = dmub_dcn20_is_hw_init; + funcs->set_gpint = dmub_dcn20_set_gpint; + funcs->is_gpint_acked = dmub_dcn20_is_gpint_acked; + funcs->get_gpint_response = dmub_dcn20_get_gpint_response; if (asic == DMUB_ASIC_DCN21) { dmub->regs = &dmub_srv_dcn21_regs; @@ -522,3 +525,50 @@ enum dmub_status dmub_srv_wait_for_idle(struct dmub_srv *dmub, return DMUB_STATUS_TIMEOUT; } + +enum dmub_status +dmub_srv_send_gpint_command(struct dmub_srv *dmub, + enum dmub_gpint_command command_code, + uint16_t param, uint32_t timeout_us) +{ + union dmub_gpint_data_register reg; + uint32_t i; + + if (!dmub->sw_init) + return DMUB_STATUS_INVALID; + + if (!dmub->hw_funcs.set_gpint) + return DMUB_STATUS_INVALID; + + if (!dmub->hw_funcs.is_gpint_acked) + return DMUB_STATUS_INVALID; + + reg.bits.status = 1; + reg.bits.command_code = command_code; + reg.bits.param = param; + + dmub->hw_funcs.set_gpint(dmub, reg); + + for (i = 0; i < timeout_us; ++i) { + if (dmub->hw_funcs.is_gpint_acked(dmub, reg)) + return DMUB_STATUS_OK; + } + + return DMUB_STATUS_TIMEOUT; +} + +enum dmub_status dmub_srv_get_gpint_response(struct dmub_srv *dmub, + uint32_t *response) +{ + *response = 0; + + if (!dmub->sw_init) + return DMUB_STATUS_INVALID; + + if (!dmub->hw_funcs.get_gpint_response) + return DMUB_STATUS_INVALID; + + *response = dmub->hw_funcs.get_gpint_response(dmub); + + return DMUB_STATUS_OK; +} -- cgit From b1e9da7f7dd4a7bfeb8c0819cfd97db672229e42 Mon Sep 17 00:00:00 2001 From: Nicholas Kazlauskas Date: Thu, 16 Jan 2020 09:16:18 -0500 Subject: drm/amd/display: Wait for clean shutdown in DMCUB reset [Why] The DMCUB may be currently executing commands when the reset is triggered. Before issuing a reset we should first wait for the DMCUB to finish its work. [How] Send the GPINT command for halting the firmware before reset. Get the ack for the command then wait for the scratch register to become the correct value. We want this to take under ~40us or so at most before we force reset to cover PHY delay sequence max time. Each register read will be at least ~1-3us so don't bother using udelay. Signed-off-by: Nicholas Kazlauskas Reviewed-by: Tony Cheng Acked-by: Bhawanpreet Lakha Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dmub/inc/dmub_gpint_cmd.h | 6 ++++ drivers/gpu/drm/amd/display/dmub/src/dmub_dcn20.c | 36 ++++++++++++++++++++++ 2 files changed, 42 insertions(+) (limited to 'drivers/gpu/drm/amd/display') diff --git a/drivers/gpu/drm/amd/display/dmub/inc/dmub_gpint_cmd.h b/drivers/gpu/drm/amd/display/dmub/inc/dmub_gpint_cmd.h index 5398ed6b35d1..e13685917dab 100644 --- a/drivers/gpu/drm/amd/display/dmub/inc/dmub_gpint_cmd.h +++ b/drivers/gpu/drm/amd/display/dmub/inc/dmub_gpint_cmd.h @@ -65,4 +65,10 @@ enum dmub_gpint_command { DMUB_GPINT__STOP_FW = 2, }; +/** + * Command responses. + */ + +#define DMUB_GPINT__STOP_FW_RESPONSE 0xDEADDEAD + #endif /* _DMUB_GPINT_CMD_H_ */ diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn20.c b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn20.c index 7c1604c2221c..479f17bb3800 100644 --- a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn20.c +++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn20.c @@ -77,6 +77,42 @@ static inline void dmub_dcn20_translate_addr(const union dmub_addr *addr_in, void dmub_dcn20_reset(struct dmub_srv *dmub) { + union dmub_gpint_data_register cmd; + const uint32_t timeout = 30; + uint32_t in_reset, scratch, i; + + REG_GET(DMCUB_CNTL, DMCUB_SOFT_RESET, &in_reset); + + if (in_reset == 0) { + cmd.bits.status = 1; + cmd.bits.command_code = DMUB_GPINT__STOP_FW; + cmd.bits.param = 0; + + dmub->hw_funcs.set_gpint(dmub, cmd); + + /** + * Timeout covers both the ACK and the wait + * for remaining work to finish. + * + * This is mostly bound by the PHY disable sequence. + * Each register check will be greater than 1us, so + * don't bother using udelay. + */ + + for (i = 0; i < timeout; ++i) { + if (dmub->hw_funcs.is_gpint_acked(dmub, cmd)) + break; + } + + for (i = 0; i < timeout; ++i) { + scratch = dmub->hw_funcs.get_gpint_response(dmub); + if (scratch == DMUB_GPINT__STOP_FW_RESPONSE) + break; + } + + /* Force reset in case we timed out, DMCUB is likely hung. */ + } + REG_UPDATE(DMCUB_CNTL, DMCUB_SOFT_RESET, 1); REG_UPDATE(DMCUB_CNTL, DMCUB_ENABLE, 0); REG_UPDATE(MMHUBBUB_SOFT_RESET, DMUIF_SOFT_RESET, 1); -- cgit From 009114f6df84150a567b05537aa29b9d660e419b Mon Sep 17 00:00:00 2001 From: Anthony Koo Date: Tue, 14 Jan 2020 17:04:24 -0500 Subject: drm/amd/display: Added locking for atomic update stream and update planes [Why] Screen flickering when HDR switches between FP16 and ARGB2101010 [How] Moved pipe_control_lock so stream update and plane update occur atomically Signed-off-by: Anthony Koo Signed-off-by: Lucy Li Reviewed-by: Aric Cyr Acked-by: Bhawanpreet Lakha Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 87 ++++++++++++++---- .../amd/display/dc/dce110/dce110_hw_sequencer.c | 23 +---- .../drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 32 +------ .../drm/amd/display/dc/dcn10/dcn10_hw_sequencer.h | 4 + drivers/gpu/drm/amd/display/dc/dcn10/dcn10_init.c | 1 + drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c | 101 +++++++++------------ drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.h | 4 - drivers/gpu/drm/amd/display/dc/dcn20/dcn20_init.c | 2 +- drivers/gpu/drm/amd/display/dc/dcn21/dcn21_init.c | 2 +- drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h | 4 +- 10 files changed, 125 insertions(+), 135 deletions(-) (limited to 'drivers/gpu/drm/amd/display') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index c9c7cf00976f..2208282ea6cb 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -761,6 +761,29 @@ static bool disable_all_writeback_pipes_for_stream( return true; } +void apply_ctx_interdependent_lock(struct dc *dc, struct dc_state *context, struct dc_stream_state *stream, bool lock) +{ + int i = 0; + + /* Checks if interdependent update function pointer is NULL or not, takes care of DCE110 case */ + if (dc->hwss.interdependent_update_lock) + dc->hwss.interdependent_update_lock(dc, context, lock); + else { + for (i = 0; i < dc->res_pool->pipe_count; i++) { + struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; + struct pipe_ctx *old_pipe_ctx = &dc->current_state->res_ctx.pipe_ctx[i]; + + // Copied conditions that were previously in dce110_apply_ctx_for_surface + if (stream == pipe_ctx->stream) { + if (!pipe_ctx->top_pipe && + (pipe_ctx->plane_state || old_pipe_ctx->plane_state)) + dc->hwss.pipe_control_lock(dc, pipe_ctx, lock); + break; + } + } + } +} + static void disable_dangling_plane(struct dc *dc, struct dc_state *context) { int i, j; @@ -786,12 +809,17 @@ static void disable_dangling_plane(struct dc *dc, struct dc_state *context) if (should_disable && old_stream) { dc_rem_all_planes_for_stream(dc, old_stream, dangling_context); disable_all_writeback_pipes_for_stream(dc, old_stream, dangling_context); + if (dc->hwss.apply_ctx_for_surface) { + apply_ctx_interdependent_lock(dc, dc->current_state, old_stream, true); dc->hwss.apply_ctx_for_surface(dc, old_stream, 0, dangling_context); + apply_ctx_interdependent_lock(dc, dc->current_state, old_stream, false); dc->hwss.post_unlock_program_front_end(dc, dangling_context); } if (dc->hwss.program_front_end_for_ctx) { + dc->hwss.interdependent_update_lock(dc, dc->current_state, true); dc->hwss.program_front_end_for_ctx(dc, dangling_context); + dc->hwss.interdependent_update_lock(dc, dc->current_state, false); dc->hwss.post_unlock_program_front_end(dc, dangling_context); } } @@ -1214,17 +1242,19 @@ static enum dc_status dc_commit_state_no_check(struct dc *dc, struct dc_state *c /* re-program planes for existing stream, in case we need to * free up plane resource for later use */ - if (dc->hwss.apply_ctx_for_surface) + if (dc->hwss.apply_ctx_for_surface) { for (i = 0; i < context->stream_count; i++) { if (context->streams[i]->mode_changed) continue; - + apply_ctx_interdependent_lock(dc, context, context->streams[i], true); dc->hwss.apply_ctx_for_surface( dc, context->streams[i], context->stream_status[i].plane_count, context); /* use new pipe config in new context */ + apply_ctx_interdependent_lock(dc, context, context->streams[i], false); dc->hwss.post_unlock_program_front_end(dc, context); } + } /* Program hardware */ for (i = 0; i < dc->res_pool->pipe_count; i++) { @@ -1244,10 +1274,11 @@ static enum dc_status dc_commit_state_no_check(struct dc *dc, struct dc_state *c /* Program all planes within new context*/ if (dc->hwss.program_front_end_for_ctx) { + dc->hwss.interdependent_update_lock(dc, context, true); dc->hwss.program_front_end_for_ctx(dc, context); + dc->hwss.interdependent_update_lock(dc, context, false); dc->hwss.post_unlock_program_front_end(dc, context); } - for (i = 0; i < context->stream_count; i++) { const struct dc_link *link = context->streams[i]->link; @@ -1255,10 +1286,12 @@ static enum dc_status dc_commit_state_no_check(struct dc *dc, struct dc_state *c continue; if (dc->hwss.apply_ctx_for_surface) { + apply_ctx_interdependent_lock(dc, context, context->streams[i], true); dc->hwss.apply_ctx_for_surface( dc, context->streams[i], context->stream_status[i].plane_count, context); + apply_ctx_interdependent_lock(dc, context, context->streams[i], false); dc->hwss.post_unlock_program_front_end(dc, context); } @@ -2105,15 +2138,10 @@ static void commit_planes_do_stream_update(struct dc *dc, if (update_type == UPDATE_TYPE_FAST) continue; - if (stream_update->dsc_config && dc->hwss.pipe_control_lock_global) { - dc->hwss.pipe_control_lock_global(dc, pipe_ctx, true); + if (stream_update->dsc_config) dp_update_dsc_config(pipe_ctx); - dc->hwss.pipe_control_lock_global(dc, pipe_ctx, false); - } if (stream_update->dpms_off) { - dc->hwss.pipe_control_lock(dc, pipe_ctx, true); - if (*stream_update->dpms_off) { core_link_disable_stream(pipe_ctx); /* for dpms, keep acquired resources*/ @@ -2127,8 +2155,6 @@ static void commit_planes_do_stream_update(struct dc *dc, core_link_enable_stream(dc->current_state, pipe_ctx); } - - dc->hwss.pipe_control_lock(dc, pipe_ctx, false); } if (stream_update->abm_level && pipe_ctx->stream_res.abm) { @@ -2184,6 +2210,27 @@ static void commit_planes_for_stream(struct dc *dc, context_clock_trace(dc, context); } + for (j = 0; j < dc->res_pool->pipe_count; j++) { + struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j]; + + if (!pipe_ctx->top_pipe && + !pipe_ctx->prev_odm_pipe && + pipe_ctx->stream && + pipe_ctx->stream == stream) { + top_pipe_to_program = pipe_ctx; + } + } + + if ((update_type != UPDATE_TYPE_FAST) && dc->hwss.interdependent_update_lock) + dc->hwss.interdependent_update_lock(dc, context, true); + else + /* Lock the top pipe while updating plane addrs, since freesync requires + * plane addr update event triggers to be synchronized. + * top_pipe_to_program is expected to never be NULL + */ + dc->hwss.pipe_control_lock(dc, top_pipe_to_program, true); + + // Stream updates if (stream_update) commit_planes_do_stream_update(dc, stream, stream_update, update_type, context); @@ -2198,6 +2245,11 @@ static void commit_planes_for_stream(struct dc *dc, if (dc->hwss.program_front_end_for_ctx) dc->hwss.program_front_end_for_ctx(dc, context); + if ((update_type != UPDATE_TYPE_FAST) && dc->hwss.interdependent_update_lock) + dc->hwss.interdependent_update_lock(dc, context, false); + else + dc->hwss.pipe_control_lock(dc, top_pipe_to_program, false); + dc->hwss.post_unlock_program_front_end(dc, context); return; } @@ -2234,8 +2286,6 @@ static void commit_planes_for_stream(struct dc *dc, pipe_ctx->stream == stream) { struct dc_stream_status *stream_status = NULL; - top_pipe_to_program = pipe_ctx; - if (!pipe_ctx->plane_state) continue; @@ -2280,12 +2330,6 @@ static void commit_planes_for_stream(struct dc *dc, // Update Type FAST, Surface updates if (update_type == UPDATE_TYPE_FAST) { - /* Lock the top pipe while updating plane addrs, since freesync requires - * plane addr update event triggers to be synchronized. - * top_pipe_to_program is expected to never be NULL - */ - dc->hwss.pipe_control_lock(dc, top_pipe_to_program, true); - if (dc->hwss.set_flip_control_gsl) for (i = 0; i < surface_count; i++) { struct dc_plane_state *plane_state = srf_updates[i].surface; @@ -2327,9 +2371,12 @@ static void commit_planes_for_stream(struct dc *dc, dc->hwss.update_plane_addr(dc, pipe_ctx); } } + } + if ((update_type != UPDATE_TYPE_FAST) && dc->hwss.interdependent_update_lock) + dc->hwss.interdependent_update_lock(dc, context, false); + else dc->hwss.pipe_control_lock(dc, top_pipe_to_program, false); - } if (update_type != UPDATE_TYPE_FAST) dc->hwss.post_unlock_program_front_end(dc, context); diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index a961b94aefd9..56d4ec7bdad7 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -2574,17 +2574,6 @@ static void dce110_apply_ctx_for_surface( if (dc->fbc_compressor) dc->fbc_compressor->funcs->disable_fbc(dc->fbc_compressor); - for (i = 0; i < dc->res_pool->pipe_count; i++) { - struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; - struct pipe_ctx *old_pipe_ctx = &dc->current_state->res_ctx.pipe_ctx[i]; - - if (stream == pipe_ctx->stream) { - if (!pipe_ctx->top_pipe && - (pipe_ctx->plane_state || old_pipe_ctx->plane_state)) - dc->hwss.pipe_control_lock(dc, pipe_ctx, true); - } - } - for (i = 0; i < dc->res_pool->pipe_count; i++) { struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; @@ -2607,16 +2596,6 @@ static void dce110_apply_ctx_for_surface( } - for (i = 0; i < dc->res_pool->pipe_count; i++) { - struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; - struct pipe_ctx *old_pipe_ctx = &dc->current_state->res_ctx.pipe_ctx[i]; - - if ((stream == pipe_ctx->stream) && - (!pipe_ctx->top_pipe) && - (pipe_ctx->plane_state || old_pipe_ctx->plane_state)) - dc->hwss.pipe_control_lock(dc, pipe_ctx, false); - } - if (dc->fbc_compressor) enable_fbc(dc, context); } @@ -2626,6 +2605,7 @@ static void dce110_post_unlock_program_front_end( struct dc_state *context) { } + static void dce110_power_down_fe(struct dc *dc, struct pipe_ctx *pipe_ctx) { struct dce_hwseq *hws = dc->hwseq; @@ -2742,6 +2722,7 @@ static const struct hw_sequencer_funcs dce110_funcs = { .disable_audio_stream = dce110_disable_audio_stream, .disable_plane = dce110_power_down_fe, .pipe_control_lock = dce_pipe_control_lock, + .interdependent_update_lock = NULL, .prepare_bandwidth = dce110_prepare_bandwidth, .optimize_bandwidth = dce110_optimize_bandwidth, .set_drr = set_drr, diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index a9a5a13d5edf..7fc559acffcd 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -82,7 +82,7 @@ void print_microsec(struct dc_context *dc_ctx, us_x10 % frac); } -static void dcn10_lock_all_pipes(struct dc *dc, +void dcn10_lock_all_pipes(struct dc *dc, struct dc_state *context, bool lock) { @@ -93,6 +93,7 @@ static void dcn10_lock_all_pipes(struct dc *dc, for (i = 0; i < dc->res_pool->pipe_count; i++) { pipe_ctx = &context->res_ctx.pipe_ctx[i]; tg = pipe_ctx->stream_res.tg; + /* * Only lock the top pipe's tg to prevent redundant * (un)locking. Also skip if pipe is disabled. @@ -103,9 +104,9 @@ static void dcn10_lock_all_pipes(struct dc *dc, continue; if (lock) - tg->funcs->lock(tg); + dc->hwss.pipe_control_lock(dc, pipe_ctx, true); else - tg->funcs->unlock(tg); + dc->hwss.pipe_control_lock(dc, pipe_ctx, false); } } @@ -1576,7 +1577,7 @@ void dcn10_pipe_control_lock( /* use TG master update lock to lock everything on the TG * therefore only top pipe need to lock */ - if (pipe->top_pipe) + if (!pipe || pipe->top_pipe) return; if (dc->debug.sanity_checks) @@ -2530,11 +2531,6 @@ void dcn10_apply_ctx_for_surface( if (underflow_check_delay_us != 0xFFFFFFFF && hws->funcs.did_underflow_occur) ASSERT(hws->funcs.did_underflow_occur(dc, top_pipe_to_program)); - if (interdependent_update) - dcn10_lock_all_pipes(dc, context, true); - else - dcn10_pipe_control_lock(dc, top_pipe_to_program, true); - if (underflow_check_delay_us != 0xFFFFFFFF) udelay(underflow_check_delay_us); @@ -2554,19 +2550,6 @@ void dcn10_apply_ctx_for_surface( pipe_ctx->update_flags.raw = 0; - /* - * Powergate reused pipes that are not powergated - * fairly hacky right now, using opp_id as indicator - * TODO: After move dc_post to dc_update, this will - * be removed. - */ - if (pipe_ctx->plane_state && !old_pipe_ctx->plane_state) { - if (old_pipe_ctx->stream_res.tg == tg && - old_pipe_ctx->plane_res.hubp && - old_pipe_ctx->plane_res.hubp->opp_id != OPP_ID_INVALID) - dc->hwss.disable_plane(dc, old_pipe_ctx); - } - if ((!pipe_ctx->plane_state || pipe_ctx->stream_res.tg != old_pipe_ctx->stream_res.tg) && old_pipe_ctx->plane_state && @@ -2599,11 +2582,6 @@ void dcn10_apply_ctx_for_surface( &pipe_ctx->dlg_regs, &pipe_ctx->ttu_regs); } - - if (interdependent_update) - dcn10_lock_all_pipes(dc, context, false); - else - dcn10_pipe_control_lock(dc, top_pipe_to_program, false); } void dcn10_post_unlock_program_front_end( diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.h index b523f0b8dc23..16a50e05ffbf 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.h @@ -70,6 +70,10 @@ void dcn10_reset_hw_ctx_wrap( struct dc *dc, struct dc_state *context); void dcn10_disable_plane(struct dc *dc, struct pipe_ctx *pipe_ctx); +void dcn10_lock_all_pipes( + struct dc *dc, + struct dc_state *context, + bool lock); void dcn10_apply_ctx_for_surface( struct dc *dc, const struct dc_stream_state *stream, diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_init.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_init.c index 681db997a532..b88ef9703b2b 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_init.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_init.c @@ -50,6 +50,7 @@ static const struct hw_sequencer_funcs dcn10_funcs = { .disable_audio_stream = dce110_disable_audio_stream, .disable_plane = dcn10_disable_plane, .pipe_control_lock = dcn10_pipe_control_lock, + .interdependent_update_lock = dcn10_lock_all_pipes, .prepare_bandwidth = dcn10_prepare_bandwidth, .optimize_bandwidth = dcn10_optimize_bandwidth, .set_drr = dcn10_set_drr, diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c index f36c4d1b7c30..129a91e8f250 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c @@ -1088,40 +1088,18 @@ void dcn20_enable_plane( // } } - -void dcn20_pipe_control_lock_global( - struct dc *dc, - struct pipe_ctx *pipe, - bool lock) -{ - if (lock) { - pipe->stream_res.tg->funcs->lock_doublebuffer_enable( - pipe->stream_res.tg); - pipe->stream_res.tg->funcs->lock(pipe->stream_res.tg); - } else { - pipe->stream_res.tg->funcs->unlock(pipe->stream_res.tg); - pipe->stream_res.tg->funcs->wait_for_state(pipe->stream_res.tg, - CRTC_STATE_VACTIVE); - pipe->stream_res.tg->funcs->wait_for_state(pipe->stream_res.tg, - CRTC_STATE_VBLANK); - pipe->stream_res.tg->funcs->wait_for_state(pipe->stream_res.tg, - CRTC_STATE_VACTIVE); - pipe->stream_res.tg->funcs->lock_doublebuffer_disable( - pipe->stream_res.tg); - } -} - void dcn20_pipe_control_lock( struct dc *dc, struct pipe_ctx *pipe, bool lock) { bool flip_immediate = false; + bool dig_update_required = false; /* use TG master update lock to lock everything on the TG * therefore only top pipe need to lock */ - if (pipe->top_pipe) + if (!pipe || pipe->top_pipe) return; if (pipe->plane_state != NULL) @@ -1154,6 +1132,19 @@ void dcn20_pipe_control_lock( (!flip_immediate && pipe->stream_res.gsl_group > 0)) dcn20_setup_gsl_group_as_lock(dc, pipe, flip_immediate); + if (pipe->stream && pipe->stream->update_flags.bits.dsc_changed) + dig_update_required = true; + + /* Need double buffer lock mode in order to synchronize front end pipe + * updates with dig updates. + */ + if (dig_update_required) { + if (lock) { + pipe->stream_res.tg->funcs->lock_doublebuffer_enable( + pipe->stream_res.tg); + } + } + if (pipe->plane_state != NULL && pipe->plane_state->triplebuffer_flips) { if (lock) pipe->stream_res.tg->funcs->triplebuffer_lock(pipe->stream_res.tg); @@ -1165,6 +1156,19 @@ void dcn20_pipe_control_lock( else pipe->stream_res.tg->funcs->unlock(pipe->stream_res.tg); } + + if (dig_update_required) { + if (!lock) { + pipe->stream_res.tg->funcs->wait_for_state(pipe->stream_res.tg, + CRTC_STATE_VACTIVE); + pipe->stream_res.tg->funcs->wait_for_state(pipe->stream_res.tg, + CRTC_STATE_VBLANK); + pipe->stream_res.tg->funcs->wait_for_state(pipe->stream_res.tg, + CRTC_STATE_VACTIVE); + pipe->stream_res.tg->funcs->lock_doublebuffer_disable( + pipe->stream_res.tg); + } + } } static void dcn20_detect_pipe_changes(struct pipe_ctx *old_pipe, struct pipe_ctx *new_pipe) @@ -1536,26 +1540,28 @@ static void dcn20_program_pipe( } } -static bool does_pipe_need_lock(struct pipe_ctx *pipe) -{ - if ((pipe->plane_state && pipe->plane_state->update_flags.raw) - || pipe->update_flags.raw) - return true; - if (pipe->bottom_pipe) - return does_pipe_need_lock(pipe->bottom_pipe); - - return false; -} - void dcn20_program_front_end_for_ctx( struct dc *dc, struct dc_state *context) { int i; struct dce_hwseq *hws = dc->hwseq; - bool pipe_locked[MAX_PIPES] = {false}; DC_LOGGER_INIT(dc->ctx->logger); + for (i = 0; i < dc->res_pool->pipe_count; i++) { + struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; + + if (!pipe_ctx->top_pipe && !pipe_ctx->prev_odm_pipe && pipe_ctx->plane_state) { + ASSERT(!pipe_ctx->plane_state->triplebuffer_flips); + if (dc->hwss.program_triplebuffer != NULL && + !dc->debug.disable_tri_buf) { + /*turn off triple buffer for full update*/ + dc->hwss.program_triplebuffer( + dc, pipe_ctx, pipe_ctx->plane_state->triplebuffer_flips); + } + } + } + /* Carry over GSL groups in case the context is changing. */ for (i = 0; i < dc->res_pool->pipe_count; i++) if (context->res_ctx.pipe_ctx[i].stream == dc->current_state->res_ctx.pipe_ctx[i].stream) @@ -1566,17 +1572,6 @@ void dcn20_program_front_end_for_ctx( for (i = 0; i < dc->res_pool->pipe_count; i++) dcn20_detect_pipe_changes(&dc->current_state->res_ctx.pipe_ctx[i], &context->res_ctx.pipe_ctx[i]); - for (i = 0; i < dc->res_pool->pipe_count; i++) - if (!context->res_ctx.pipe_ctx[i].top_pipe && - does_pipe_need_lock(&context->res_ctx.pipe_ctx[i])) { - struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; - - if (pipe_ctx->update_flags.bits.tg_changed || pipe_ctx->update_flags.bits.enable) - dc->hwss.pipe_control_lock(dc, pipe_ctx, true); - if (!pipe_ctx->update_flags.bits.enable) - dc->hwss.pipe_control_lock(dc, &dc->current_state->res_ctx.pipe_ctx[i], true); - pipe_locked[i] = true; - } /* OTG blank before disabling all front ends */ for (i = 0; i < dc->res_pool->pipe_count; i++) @@ -1614,17 +1609,6 @@ void dcn20_program_front_end_for_ctx( hws->funcs.program_all_writeback_pipes_in_tree(dc, pipe->stream, context); } } - - /* Unlock all locked pipes */ - for (i = 0; i < dc->res_pool->pipe_count; i++) - if (pipe_locked[i]) { - struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; - - if (pipe_ctx->update_flags.bits.tg_changed || pipe_ctx->update_flags.bits.enable) - dc->hwss.pipe_control_lock(dc, pipe_ctx, false); - if (!pipe_ctx->update_flags.bits.enable) - dc->hwss.pipe_control_lock(dc, &dc->current_state->res_ctx.pipe_ctx[i], false); - } } void dcn20_post_unlock_program_front_end( @@ -1664,7 +1648,6 @@ void dcn20_post_unlock_program_front_end( dc->res_pool->hubbub->funcs->apply_DEDCN21_147_wa(dc->res_pool->hubbub); } - void dcn20_prepare_bandwidth( struct dc *dc, struct dc_state *context) diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.h b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.h index 80f192b8b3a2..63ce763f148e 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.h +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.h @@ -61,10 +61,6 @@ void dcn20_pipe_control_lock( struct dc *dc, struct pipe_ctx *pipe, bool lock); -void dcn20_pipe_control_lock_global( - struct dc *dc, - struct pipe_ctx *pipe, - bool lock); void dcn20_prepare_bandwidth( struct dc *dc, struct dc_state *context); diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_init.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_init.c index cb0cb999251e..44ec5f5f9fd2 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_init.c +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_init.c @@ -51,7 +51,7 @@ static const struct hw_sequencer_funcs dcn20_funcs = { .disable_audio_stream = dce110_disable_audio_stream, .disable_plane = dcn20_disable_plane, .pipe_control_lock = dcn20_pipe_control_lock, - .pipe_control_lock_global = dcn20_pipe_control_lock_global, + .interdependent_update_lock = dcn10_lock_all_pipes, .prepare_bandwidth = dcn20_prepare_bandwidth, .optimize_bandwidth = dcn20_optimize_bandwidth, .update_bandwidth = dcn20_update_bandwidth, diff --git a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_init.c b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_init.c index 4963a540948d..53006f3b9eb9 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_init.c +++ b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_init.c @@ -52,7 +52,7 @@ static const struct hw_sequencer_funcs dcn21_funcs = { .disable_audio_stream = dce110_disable_audio_stream, .disable_plane = dcn20_disable_plane, .pipe_control_lock = dcn20_pipe_control_lock, - .pipe_control_lock_global = dcn20_pipe_control_lock_global, + .interdependent_update_lock = dcn10_lock_all_pipes, .prepare_bandwidth = dcn20_prepare_bandwidth, .optimize_bandwidth = dcn20_optimize_bandwidth, .update_bandwidth = dcn20_update_bandwidth, diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h index 63919866ba38..d4c1fb242c63 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h @@ -80,10 +80,10 @@ struct hw_sequencer_funcs { void (*update_pending_status)(struct pipe_ctx *pipe_ctx); /* Pipe Lock Related */ - void (*pipe_control_lock_global)(struct dc *dc, - struct pipe_ctx *pipe, bool lock); void (*pipe_control_lock)(struct dc *dc, struct pipe_ctx *pipe, bool lock); + void (*interdependent_update_lock)(struct dc *dc, + struct dc_state *context, bool lock); void (*set_flip_control_gsl)(struct pipe_ctx *pipe_ctx, bool flip_immediate); -- cgit From 3ba28b639d653d58e918eb854de26f0d01cc7d5b Mon Sep 17 00:00:00 2001 From: Aric Cyr Date: Sat, 18 Jan 2020 14:03:55 -0500 Subject: drm/amd/display: Fix GSL acquire [Why] After locking refactor GSL is not acquired properly resulting in immediate flip issues. [How] Do not copy old GSL state anymore since GSL is acquired earlier now. Signed-off-by: Aric Cyr Reviewed-by: Anthony Koo Acked-by: Bhawanpreet Lakha Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c | 6 ------ 1 file changed, 6 deletions(-) (limited to 'drivers/gpu/drm/amd/display') diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c index 129a91e8f250..9713f452debf 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c @@ -1562,12 +1562,6 @@ void dcn20_program_front_end_for_ctx( } } - /* Carry over GSL groups in case the context is changing. */ - for (i = 0; i < dc->res_pool->pipe_count; i++) - if (context->res_ctx.pipe_ctx[i].stream == dc->current_state->res_ctx.pipe_ctx[i].stream) - context->res_ctx.pipe_ctx[i].stream_res.gsl_group = - dc->current_state->res_ctx.pipe_ctx[i].stream_res.gsl_group; - /* Set pipe update flags and lock pipes */ for (i = 0; i < dc->res_pool->pipe_count; i++) dcn20_detect_pipe_changes(&dc->current_state->res_ctx.pipe_ctx[i], -- cgit From 2c278f016d309fc523f3b3cd766849bf0da98245 Mon Sep 17 00:00:00 2001 From: Aric Cyr Date: Sat, 18 Jan 2020 22:50:59 -0500 Subject: drm/amd/display: remove unused variable Signed-off-by: Aric Cyr Reviewed-by: Aric Cyr Acked-by: Bhawanpreet Lakha Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc.h | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/gpu/drm/amd/display') diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index e8d126890d7e..d00b72df469a 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -682,7 +682,6 @@ struct dc_3dlut { struct kref refcount; struct tetrahedral_params lut_3d; struct fixed31_32 hdr_multiplier; - bool initialized; /*remove after diag fix*/ union dc_3dlut_state state; struct dc_context *ctx; }; -- cgit From 76c332c3d45b7b9a7db6830d84e5b3223d5cc920 Mon Sep 17 00:00:00 2001 From: Aric Cyr Date: Mon, 20 Jan 2020 08:15:27 -0500 Subject: drm/amd/display: 3.2.70 Signed-off-by: Aric Cyr Reviewed-by: Aric Cyr Acked-by: Bhawanpreet Lakha Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu/drm/amd/display') diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index d00b72df469a..7be2023f1a66 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -39,7 +39,7 @@ #include "inc/hw/dmcu.h" #include "dml/display_mode_lib.h" -#define DC_VER "3.2.69" +#define DC_VER "3.2.70" #define MAX_SURFACES 3 #define MAX_PLANES 6 -- cgit From 68bbca15e7062f4ae16531e29893f78d0b4840b6 Mon Sep 17 00:00:00 2001 From: Peikang Zhang Date: Mon, 20 Jan 2020 09:25:15 -0500 Subject: drm/amd/display: dc_get_vmid_use_vector() crashes when get called [Why] int i can go out of boundary which will cause crash [How] Fixed the maximum value of i to avoid i going out of boundary Signed-off-by: Peikang Zhang Reviewed-by: Jun Lei Acked-by: Bhawanpreet Lakha Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_vm_helper.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu/drm/amd/display') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_vm_helper.c b/drivers/gpu/drm/amd/display/dc/core/dc_vm_helper.c index a96d8de9380e..f2b39ec35c89 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_vm_helper.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_vm_helper.c @@ -62,7 +62,7 @@ int dc_get_vmid_use_vector(struct dc *dc) int i; int in_use = 0; - for (i = 0; i < dc->vm_helper->num_vmid; i++) + for (i = 0; i < MAX_HUBP; i++) in_use |= dc->vm_helper->hubp_vmid_usage[i].vmid_usage[0] | dc->vm_helper->hubp_vmid_usage[i].vmid_usage[1]; return in_use; -- cgit From 6409e2552ffc8784581820dd72730a64dda66743 Mon Sep 17 00:00:00 2001 From: Roman Li Date: Thu, 30 Jan 2020 15:43:07 -0500 Subject: drm/amd/display: remove early break in interdependent_lock [Why] The break in apply_ctx_interdependent_lock() may potentially lead to early break from the loop leaving update plane unlocked [How] Remove break Signed-off-by: Roman Li Reviewed-by: Anthony Koo Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/gpu/drm/amd/display') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 2208282ea6cb..7fdd82b7708a 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -778,7 +778,6 @@ void apply_ctx_interdependent_lock(struct dc *dc, struct dc_state *context, stru if (!pipe_ctx->top_pipe && (pipe_ctx->plane_state || old_pipe_ctx->plane_state)) dc->hwss.pipe_control_lock(dc, pipe_ctx, lock); - break; } } } -- cgit From 76162cb77a132b32fc0b99b5d0782b8129476db5 Mon Sep 17 00:00:00 2001 From: Peikang Zhang Date: Wed, 15 Jan 2020 15:45:10 -0500 Subject: drm/amd/display: Update hubbub description comment Description for DCHUBBUB_TEST_DEBUG_DATA is changed to avoid any future confusions. Signed-off-by: Peikang Zhang Reviewed-by: Aric Cyr Acked-by: Bhawanpreet Lakha Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/dcn10/dcn10_hubbub.c | 63 ++-------------------- 1 file changed, 3 insertions(+), 60 deletions(-) (limited to 'drivers/gpu/drm/amd/display') diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubbub.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubbub.c index f36a0d8cedfe..870735deaca7 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubbub.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubbub.c @@ -147,8 +147,9 @@ bool hubbub1_verify_allow_pstate_change_high( forced_pstate_allow = false; } - /* RV2: - * dchubbubdebugind, at: 0xB + /* The following table only applies to DCN1 and DCN2, + * for newer DCNs, need to consult with HW IP folks to read RTL + * HUBBUB:DCHUBBUB_TEST_ARB_DEBUG10 DCHUBBUBDEBUGIND:0xB * description * 0: Pipe0 Plane0 Allow Pstate Change * 1: Pipe0 Plane1 Allow Pstate Change @@ -181,64 +182,6 @@ bool hubbub1_verify_allow_pstate_change_high( * 28: WB0 Allow Pstate Change * 29: WB1 Allow Pstate Change * 30: Arbiter's allow_pstate_change - * 31: SOC pstate change request" - */ - /*DCN2.x: - HUBBUB:DCHUBBUB_TEST_ARB_DEBUG10 DCHUBBUBDEBUGIND:0xB - 0: Pipe0 Plane0 Allow P-state Change - 1: Pipe0 Plane1 Allow P-state Change - 2: Pipe0 Cursor0 Allow P-state Change - 3: Pipe0 Cursor1 Allow P-state Change - 4: Pipe1 Plane0 Allow P-state Change - 5: Pipe1 Plane1 Allow P-state Change - 6: Pipe1 Cursor0 Allow P-state Change - 7: Pipe1 Cursor1 Allow P-state Change - 8: Pipe2 Plane0 Allow P-state Change - 9: Pipe2 Plane1 Allow P-state Change - 10: Pipe2 Cursor0 Allow P-state Change - 11: Pipe2 Cursor1 Allow P-state Change - 12: Pipe3 Plane0 Allow P-state Change - 13: Pipe3 Plane1 Allow P-state Change - 14: Pipe3 Cursor0 Allow P-state Change - 15: Pipe3 Cursor1 Allow P-state Change - 16: Pipe4 Plane0 Allow P-state Change - 17: Pipe4 Plane1 Allow P-state Change - 18: Pipe4 Cursor0 Allow P-state Change - 19: Pipe4 Cursor1 Allow P-state Change - 20: Pipe5 Plane0 Allow P-state Change - 21: Pipe5 Plane1 Allow P-state Change - 22: Pipe5 Cursor0 Allow P-state Change - 23: Pipe5 Cursor1 Allow P-state Change - 24: Pipe6 Plane0 Allow P-state Change - 25: Pipe6 Plane1 Allow P-state Change - 26: Pipe6 Cursor0 Allow P-state Change - 27: Pipe6 Cursor1 Allow P-state Change - 28: WB0 Allow P-state Change - 29: WB1 Allow P-state Change - 30: Arbiter`s Allow P-state Change - 31: SOC P-state Change request - */ - /* RV1: - * dchubbubdebugind, at: 0x7 - * description "3-0: Pipe0 cursor0 QOS - * 7-4: Pipe1 cursor0 QOS - * 11-8: Pipe2 cursor0 QOS - * 15-12: Pipe3 cursor0 QOS - * 16: Pipe0 Plane0 Allow Pstate Change - * 17: Pipe1 Plane0 Allow Pstate Change - * 18: Pipe2 Plane0 Allow Pstate Change - * 19: Pipe3 Plane0 Allow Pstate Change - * 20: Pipe0 Plane1 Allow Pstate Change - * 21: Pipe1 Plane1 Allow Pstate Change - * 22: Pipe2 Plane1 Allow Pstate Change - * 23: Pipe3 Plane1 Allow Pstate Change - * 24: Pipe0 cursor0 Allow Pstate Change - * 25: Pipe1 cursor0 Allow Pstate Change - * 26: Pipe2 cursor0 Allow Pstate Change - * 27: Pipe3 cursor0 Allow Pstate Change - * 28: WB0 Allow Pstate Change - * 29: WB1 Allow Pstate Change - * 30: Arbiter's allow_pstate_change * 31: SOC pstate change request */ -- cgit From 3f0940f8691a295234ed25b94cafe0467af8a50b Mon Sep 17 00:00:00 2001 From: Charlene Liu Date: Fri, 10 Jan 2020 14:52:49 -0500 Subject: drm/amd/display: add stream_enc_inst for PSP HDCP inst use [why] new HW engine mapping requirment use in PSP [how] report stream_enc_inst Signed-off-by: Charlene Liu Reviewed-by: Wenjing Liu Acked-by: Bhawanpreet Lakha Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 3 ++- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 2 +- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.c | 1 + drivers/gpu/drm/amd/display/dc/dcn20/dcn20_stream_encoder.c | 1 + drivers/gpu/drm/amd/display/dc/inc/hw/stream_encoder.h | 1 + 5 files changed, 6 insertions(+), 2 deletions(-) (limited to 'drivers/gpu/drm/amd/display') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index 41184e593f85..fe50747692ec 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -2922,7 +2922,8 @@ static void update_psp_stream_config(struct pipe_ctx *pipe_ctx, bool dpms_off) memset(&config, 0, sizeof(config)); config.otg_inst = (uint8_t) pipe_ctx->stream_res.tg->inst; - config.stream_enc_inst = (uint8_t) pipe_ctx->stream_res.stream_enc->id; + /*stream_enc_inst*/ + config.stream_enc_inst = (uint8_t) pipe_ctx->stream_res.stream_enc->stream_enc_inst; config.link_enc_inst = pipe_ctx->stream->link->link_enc_hw_inst; config.dpms_off = dpms_off; config.dm_stream_ctx = pipe_ctx->stream->dm_stream_context; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index a0eb9e533a61..cd80d8249d14 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -2034,7 +2034,7 @@ enum dc_status resource_map_pool_resources( for (i = 0; i < context->stream_count; i++) if (context->streams[i] == stream) { context->stream_status[i].primary_otg_inst = pipe_ctx->stream_res.tg->inst; - context->stream_status[i].stream_enc_inst = pipe_ctx->stream_res.stream_enc->id; + context->stream_status[i].stream_enc_inst = pipe_ctx->stream_res.stream_enc->stream_enc_inst; context->stream_status[i].audio_inst = pipe_ctx->stream_res.audio ? pipe_ctx->stream_res.audio->inst : -1; diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.c index 376c4264d295..7eba9333c328 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.c @@ -1667,5 +1667,6 @@ void dcn10_stream_encoder_construct( enc1->regs = regs; enc1->se_shift = se_shift; enc1->se_mask = se_mask; + enc1->base.stream_enc_inst = eng_id - ENGINE_ID_DIGA; } diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_stream_encoder.c index 9b70a1e7b962..99a7ef6ab878 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_stream_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_stream_encoder.c @@ -616,5 +616,6 @@ void dcn20_stream_encoder_construct( enc1->regs = regs; enc1->se_shift = se_shift; enc1->se_mask = se_mask; + enc1->base.stream_enc_inst = eng_id - ENGINE_ID_DIGA; } diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/stream_encoder.h b/drivers/gpu/drm/amd/display/dc/inc/hw/stream_encoder.h index 351b387ad606..ac6523c0828e 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/stream_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/stream_encoder.h @@ -103,6 +103,7 @@ struct stream_encoder { struct dc_context *ctx; struct dc_bios *bp; enum engine_id id; + uint32_t stream_enc_inst; }; struct enc_state { -- cgit From 84fc79899ee7a20b65e91b533b63530141896f8c Mon Sep 17 00:00:00 2001 From: Sung Lee Date: Mon, 20 Jan 2020 18:58:45 -0500 Subject: drm/amd/display: Use dcfclk to populate watermark ranges [WHY & HOW] Previously drain clk was unconstrained and fill clk was constrained on fclk. We want to change it to fill clk unconstrained and drain clock constrained to dcfclk. Signed-off-by: Sung Lee Reviewed-by: Tony Cheng Acked-by: Bhawanpreet Lakha Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'drivers/gpu/drm/amd/display') diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c index 7ae4c06232dd..034a5852a416 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c @@ -412,19 +412,19 @@ void build_watermark_ranges(struct clk_bw_params *bw_params, struct pp_smu_wm_ra ranges->reader_wm_sets[num_valid_sets].wm_inst = bw_params->wm_table.entries[i].wm_inst; ranges->reader_wm_sets[num_valid_sets].wm_type = bw_params->wm_table.entries[i].wm_type; - /* We will not select WM based on dcfclk, so leave it as unconstrained */ - ranges->reader_wm_sets[num_valid_sets].min_drain_clk_mhz = PP_SMU_WM_SET_RANGE_CLK_UNCONSTRAINED_MIN; - ranges->reader_wm_sets[num_valid_sets].max_drain_clk_mhz = PP_SMU_WM_SET_RANGE_CLK_UNCONSTRAINED_MAX; - /* fclk wil be used to select WM*/ + /* We will not select WM based on fclk, so leave it as unconstrained */ + ranges->reader_wm_sets[num_valid_sets].min_fill_clk_mhz = PP_SMU_WM_SET_RANGE_CLK_UNCONSTRAINED_MIN; + ranges->reader_wm_sets[num_valid_sets].max_fill_clk_mhz = PP_SMU_WM_SET_RANGE_CLK_UNCONSTRAINED_MAX; + /* dcfclk wil be used to select WM*/ if (ranges->reader_wm_sets[num_valid_sets].wm_type == WM_TYPE_PSTATE_CHG) { if (i == 0) - ranges->reader_wm_sets[num_valid_sets].min_fill_clk_mhz = 0; + ranges->reader_wm_sets[num_valid_sets].min_drain_clk_mhz = 0; else { /* add 1 to make it non-overlapping with next lvl */ - ranges->reader_wm_sets[num_valid_sets].min_fill_clk_mhz = bw_params->clk_table.entries[i - 1].fclk_mhz + 1; + ranges->reader_wm_sets[num_valid_sets].min_drain_clk_mhz = bw_params->clk_table.entries[i - 1].dcfclk_mhz + 1; } - ranges->reader_wm_sets[num_valid_sets].max_fill_clk_mhz = bw_params->clk_table.entries[i].fclk_mhz; + ranges->reader_wm_sets[num_valid_sets].max_drain_clk_mhz = bw_params->clk_table.entries[i].dcfclk_mhz; } else { /* unconstrained for memory retraining */ -- cgit From 28e7a7f4fb4b9dc364a054ae01b87f7111d5ba2d Mon Sep 17 00:00:00 2001 From: Aric Cyr Date: Tue, 21 Jan 2020 22:50:13 -0500 Subject: drm/amd/display: Check engine is not NULL before acquiring [Why] Engine can be NULL in some cases, so we must not acquire it. [How] Check for NULL engine before acquiring. Signed-off-by: Aric Cyr Reviewed-by: Harry Wentland Acked-by: Bhawanpreet Lakha Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce/dce_aux.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu/drm/amd/display') diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_aux.c b/drivers/gpu/drm/amd/display/dc/dce/dce_aux.c index f1a5d2c6aa37..68c4049cbc2a 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_aux.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_aux.c @@ -400,7 +400,7 @@ static bool acquire( { enum gpio_result result; - if (!is_engine_available(engine)) + if ((engine == NULL) || !is_engine_available(engine)) return false; result = dal_ddc_open(ddc, GPIO_MODE_HARDWARE, -- cgit From 71b81f1275e0b5713fae86004be72719a2fa73b7 Mon Sep 17 00:00:00 2001 From: Wenjing Liu Date: Wed, 22 Jan 2020 11:54:54 -0500 Subject: drm/amd/display: decouple global lock out of pipe control lock [why] hwss should not guess what type of pipe lock is needed. The caller of the lock function should know the right type of pipe lock. Decouple the setup of global lock outside of pipe control lock logic. Signed-off-by: Wenjing Liu Reviewed-by: Anthony Koo Acked-by: Bhawanpreet Lakha Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 20 ++++++++++++++++ drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c | 27 ---------------------- 2 files changed, 20 insertions(+), 27 deletions(-) (limited to 'drivers/gpu/drm/amd/display') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 7fdd82b7708a..40878b86a05d 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -2220,6 +2220,11 @@ static void commit_planes_for_stream(struct dc *dc, } } + if ((update_type != UPDATE_TYPE_FAST) && stream->update_flags.bits.dsc_changed) + if (top_pipe_to_program->stream_res.tg->funcs->lock_doublebuffer_enable) + top_pipe_to_program->stream_res.tg->funcs->lock_doublebuffer_enable( + top_pipe_to_program->stream_res.tg); + if ((update_type != UPDATE_TYPE_FAST) && dc->hwss.interdependent_update_lock) dc->hwss.interdependent_update_lock(dc, context, true); else @@ -2377,6 +2382,21 @@ static void commit_planes_for_stream(struct dc *dc, else dc->hwss.pipe_control_lock(dc, top_pipe_to_program, false); + if ((update_type != UPDATE_TYPE_FAST) && stream->update_flags.bits.dsc_changed) + if (top_pipe_to_program->stream_res.tg->funcs->lock_doublebuffer_enable) { + top_pipe_to_program->stream_res.tg->funcs->wait_for_state( + top_pipe_to_program->stream_res.tg, + CRTC_STATE_VACTIVE); + top_pipe_to_program->stream_res.tg->funcs->wait_for_state( + top_pipe_to_program->stream_res.tg, + CRTC_STATE_VBLANK); + top_pipe_to_program->stream_res.tg->funcs->wait_for_state( + top_pipe_to_program->stream_res.tg, + CRTC_STATE_VACTIVE); + top_pipe_to_program->stream_res.tg->funcs->lock_doublebuffer_disable( + top_pipe_to_program->stream_res.tg); + } + if (update_type != UPDATE_TYPE_FAST) dc->hwss.post_unlock_program_front_end(dc, context); diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c index 9713f452debf..52ef4d333112 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c @@ -1094,7 +1094,6 @@ void dcn20_pipe_control_lock( bool lock) { bool flip_immediate = false; - bool dig_update_required = false; /* use TG master update lock to lock everything on the TG * therefore only top pipe need to lock @@ -1132,19 +1131,6 @@ void dcn20_pipe_control_lock( (!flip_immediate && pipe->stream_res.gsl_group > 0)) dcn20_setup_gsl_group_as_lock(dc, pipe, flip_immediate); - if (pipe->stream && pipe->stream->update_flags.bits.dsc_changed) - dig_update_required = true; - - /* Need double buffer lock mode in order to synchronize front end pipe - * updates with dig updates. - */ - if (dig_update_required) { - if (lock) { - pipe->stream_res.tg->funcs->lock_doublebuffer_enable( - pipe->stream_res.tg); - } - } - if (pipe->plane_state != NULL && pipe->plane_state->triplebuffer_flips) { if (lock) pipe->stream_res.tg->funcs->triplebuffer_lock(pipe->stream_res.tg); @@ -1156,19 +1142,6 @@ void dcn20_pipe_control_lock( else pipe->stream_res.tg->funcs->unlock(pipe->stream_res.tg); } - - if (dig_update_required) { - if (!lock) { - pipe->stream_res.tg->funcs->wait_for_state(pipe->stream_res.tg, - CRTC_STATE_VACTIVE); - pipe->stream_res.tg->funcs->wait_for_state(pipe->stream_res.tg, - CRTC_STATE_VBLANK); - pipe->stream_res.tg->funcs->wait_for_state(pipe->stream_res.tg, - CRTC_STATE_VACTIVE); - pipe->stream_res.tg->funcs->lock_doublebuffer_disable( - pipe->stream_res.tg); - } - } } static void dcn20_detect_pipe_changes(struct pipe_ctx *old_pipe, struct pipe_ctx *new_pipe) -- cgit From a39a58166901f7e72088c5eedbd17e481f0722ea Mon Sep 17 00:00:00 2001 From: Eric Yang Date: Mon, 20 Jan 2020 12:56:43 -0500 Subject: drm/amd/display: fix inputting clk lvl into dml for RN [Why] Previous logic is only good for 15W parts. Other configuration need a smarter logic to match clk levels with pp table in the fuse. [How] Cache all 8 DPM level's clock data, find lvl that match each pstate in the pp table and build input into DML base on that Signed-off-by: Eric Yang Signed-off-by: Sung Lee Reviewed-by: Tony Cheng Acked-by: Bhawanpreet Lakha Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/dcn21/dcn21_resource.c | 165 ++++++++++++++++----- .../drm/amd/display/dc/dml/display_mode_structs.h | 3 +- 2 files changed, 127 insertions(+), 41 deletions(-) (limited to 'drivers/gpu/drm/amd/display') diff --git a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c index 0d506d30d6b6..5f6fb16f16e5 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c @@ -162,10 +162,10 @@ struct _vcs_dpi_soc_bounding_box_st dcn2_1_soc = { .clock_limits = { { .state = 0, - .dcfclk_mhz = 304.0, - .fabricclk_mhz = 600.0, - .dispclk_mhz = 618.0, - .dppclk_mhz = 440.0, + .dcfclk_mhz = 400.0, + .fabricclk_mhz = 400.0, + .dispclk_mhz = 600.0, + .dppclk_mhz = 400.00, .phyclk_mhz = 600.0, .socclk_mhz = 278.0, .dscclk_mhz = 205.67, @@ -173,10 +173,10 @@ struct _vcs_dpi_soc_bounding_box_st dcn2_1_soc = { }, { .state = 1, - .dcfclk_mhz = 304.0, - .fabricclk_mhz = 600.0, - .dispclk_mhz = 618.0, - .dppclk_mhz = 618.0, + .dcfclk_mhz = 464.52, + .fabricclk_mhz = 800.0, + .dispclk_mhz = 654.55, + .dppclk_mhz = 626.09, .phyclk_mhz = 600.0, .socclk_mhz = 278.0, .dscclk_mhz = 205.67, @@ -184,32 +184,65 @@ struct _vcs_dpi_soc_bounding_box_st dcn2_1_soc = { }, { .state = 2, - .dcfclk_mhz = 608.0, - .fabricclk_mhz = 1066.0, - .dispclk_mhz = 888.0, - .dppclk_mhz = 888.0, - .phyclk_mhz = 810.0, + .dcfclk_mhz = 514.29, + .fabricclk_mhz = 933.0, + .dispclk_mhz = 757.89, + .dppclk_mhz = 685.71, + .phyclk_mhz = 600.0, .socclk_mhz = 278.0, .dscclk_mhz = 287.67, - .dram_speed_mts = 2133.0, + .dram_speed_mts = 1866.0, }, { .state = 3, - .dcfclk_mhz = 676.0, - .fabricclk_mhz = 1600.0, - .dispclk_mhz = 1015.0, - .dppclk_mhz = 1015.0, - .phyclk_mhz = 810.0, + .dcfclk_mhz = 576.00, + .fabricclk_mhz = 1067.0, + .dispclk_mhz = 847.06, + .dppclk_mhz = 757.89, + .phyclk_mhz = 600.0, .socclk_mhz = 715.0, .dscclk_mhz = 318.334, - .dram_speed_mts = 4266.0, + .dram_speed_mts = 2134.0, }, { .state = 4, - .dcfclk_mhz = 810.0, + .dcfclk_mhz = 626.09, + .fabricclk_mhz = 1200.0, + .dispclk_mhz = 900.00, + .dppclk_mhz = 847.06, + .phyclk_mhz = 810.0, + .socclk_mhz = 953.0, + .dscclk_mhz = 489.0, + .dram_speed_mts = 2400.0, + }, + { + .state = 5, + .dcfclk_mhz = 685.71, + .fabricclk_mhz = 1333.0, + .dispclk_mhz = 1028.57, + .dppclk_mhz = 960.00, + .phyclk_mhz = 810.0, + .socclk_mhz = 278.0, + .dscclk_mhz = 287.67, + .dram_speed_mts = 2666.0, + }, + { + .state = 6, + .dcfclk_mhz = 757.89, + .fabricclk_mhz = 1467.0, + .dispclk_mhz = 1107.69, + .dppclk_mhz = 1028.57, + .phyclk_mhz = 810.0, + .socclk_mhz = 715.0, + .dscclk_mhz = 318.334, + .dram_speed_mts = 3200.0, + }, + { + .state = 7, + .dcfclk_mhz = 847.06, .fabricclk_mhz = 1600.0, .dispclk_mhz = 1395.0, - .dppclk_mhz = 1285.0, + .dppclk_mhz = 1285.00, .phyclk_mhz = 1325.0, .socclk_mhz = 953.0, .dscclk_mhz = 489.0, @@ -217,8 +250,8 @@ struct _vcs_dpi_soc_bounding_box_st dcn2_1_soc = { }, /*Extra state, no dispclk ramping*/ { - .state = 5, - .dcfclk_mhz = 810.0, + .state = 8, + .dcfclk_mhz = 847.06, .fabricclk_mhz = 1600.0, .dispclk_mhz = 1395.0, .dppclk_mhz = 1285.0, @@ -265,7 +298,7 @@ struct _vcs_dpi_soc_bounding_box_st dcn2_1_soc = { .xfc_bus_transport_time_us = 4, .xfc_xbuf_latency_tolerance_us = 4, .use_urgent_burst_bw = 1, - .num_states = 5 + .num_states = 9 }; #ifndef MAX @@ -1333,26 +1366,78 @@ static void update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_param { struct dcn21_resource_pool *pool = TO_DCN21_RES_POOL(dc->res_pool); struct clk_limit_table *clk_table = &bw_params->clk_table; - int i; + unsigned int i, j, k; + int closest_clk_lvl; + + // diags does not retrieve proper values from SMU + // cap states to 5 and make state 5 the max state + if (IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment) || IS_DIAG_DC(dc->ctx->dce_environment)) { + dcn2_1_soc.num_states = 5; + + dcn2_1_soc.clock_limits[5].state = 5; + dcn2_1_soc.clock_limits[5].dcfclk_mhz = 810.0; + dcn2_1_soc.clock_limits[5].fabricclk_mhz = 1600.0; + dcn2_1_soc.clock_limits[5].dispclk_mhz = 1395.0; + dcn2_1_soc.clock_limits[5].dppclk_mhz = 1285.0; + dcn2_1_soc.clock_limits[5].phyclk_mhz = 1325.0; + dcn2_1_soc.clock_limits[5].socclk_mhz = 953.0; + dcn2_1_soc.clock_limits[5].dscclk_mhz = 489.0; + dcn2_1_soc.clock_limits[5].dram_speed_mts = 4266.0; + } else { + dcn2_1_ip.max_num_otg = pool->base.res_cap->num_timing_generator; + dcn2_1_ip.max_num_dpp = pool->base.pipe_count; + dcn2_1_soc.num_chans = bw_params->num_channels; + + /* Vmin: leave lowest DCN clocks, override with dcfclk, fclk, memclk from fuse */ + dcn2_1_soc.clock_limits[0].state = 0; + dcn2_1_soc.clock_limits[0].dcfclk_mhz = clk_table->entries[0].dcfclk_mhz; + dcn2_1_soc.clock_limits[0].fabricclk_mhz = clk_table->entries[0].fclk_mhz; + dcn2_1_soc.clock_limits[0].socclk_mhz = clk_table->entries[0].socclk_mhz; + dcn2_1_soc.clock_limits[0].dram_speed_mts = clk_table->entries[0].memclk_mhz * 2; + + /* + * Other levels: find cloest DCN clocks that fit the given clock limit using dcfclk + * as indicater + */ - dcn2_1_ip.max_num_otg = pool->base.res_cap->num_timing_generator; - dcn2_1_ip.max_num_dpp = pool->base.pipe_count; - dcn2_1_soc.num_chans = bw_params->num_channels; + closest_clk_lvl = -1; + /* index currently being filled */ + k = 1; + for (i = 1; i < clk_table->num_entries; i++) { + /* loop backwards, skip duplicate state, +1 because SMU has precision issue */ + for (j = dcn2_1_soc.num_states - 2; j >= k; j--) { + if ((unsigned int) dcn2_1_soc.clock_limits[j].dcfclk_mhz <= clk_table->entries[i].dcfclk_mhz) { + closest_clk_lvl = j; + break; + } + } - for (i = 0; i < clk_table->num_entries; i++) { + /* if found a lvl that fits, use the DCN clks from it, if not, go to next clk limit*/ + if (closest_clk_lvl != -1) { + dcn2_1_soc.clock_limits[k].state = i; + dcn2_1_soc.clock_limits[k].dcfclk_mhz = clk_table->entries[i].dcfclk_mhz; + dcn2_1_soc.clock_limits[k].fabricclk_mhz = clk_table->entries[i].fclk_mhz; + dcn2_1_soc.clock_limits[k].socclk_mhz = clk_table->entries[i].socclk_mhz; + dcn2_1_soc.clock_limits[k].dram_speed_mts = clk_table->entries[i].memclk_mhz * 2; + + dcn2_1_soc.clock_limits[k].dispclk_mhz = dcn2_1_soc.clock_limits[closest_clk_lvl].dispclk_mhz; + dcn2_1_soc.clock_limits[k].dppclk_mhz = dcn2_1_soc.clock_limits[closest_clk_lvl].dppclk_mhz; + dcn2_1_soc.clock_limits[k].dram_bw_per_chan_gbps = dcn2_1_soc.clock_limits[closest_clk_lvl].dram_bw_per_chan_gbps; + dcn2_1_soc.clock_limits[k].dscclk_mhz = dcn2_1_soc.clock_limits[closest_clk_lvl].dscclk_mhz; + dcn2_1_soc.clock_limits[k].dtbclk_mhz = dcn2_1_soc.clock_limits[closest_clk_lvl].dtbclk_mhz; + dcn2_1_soc.clock_limits[k].phyclk_d18_mhz = dcn2_1_soc.clock_limits[closest_clk_lvl].phyclk_d18_mhz; + dcn2_1_soc.clock_limits[k].phyclk_mhz = dcn2_1_soc.clock_limits[closest_clk_lvl].phyclk_mhz; + k++; + } + } - dcn2_1_soc.clock_limits[i].state = i; - dcn2_1_soc.clock_limits[i].dcfclk_mhz = clk_table->entries[i].dcfclk_mhz; - dcn2_1_soc.clock_limits[i].fabricclk_mhz = clk_table->entries[i].fclk_mhz; - dcn2_1_soc.clock_limits[i].socclk_mhz = clk_table->entries[i].socclk_mhz; - dcn2_1_soc.clock_limits[i].dram_speed_mts = clk_table->entries[i].memclk_mhz * 2; + /* duplicate last level */ + dcn2_1_soc.clock_limits[k] = dcn2_1_soc.clock_limits[k - 1]; + dcn2_1_soc.clock_limits[k].state = k; + dcn2_1_soc.num_states = k + 1; } - dcn2_1_soc.clock_limits[i] = dcn2_1_soc.clock_limits[i - 1]; - dcn2_1_soc.num_states = i; - // diags does not retrieve proper values from SMU, do not update DML instance for diags - if (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment) && !IS_DIAG_DC(dc->ctx->dce_environment)) - dml_init_instance(&dc->dml, &dcn2_1_soc, &dcn2_1_ip, DML_PROJECT_DCN21); + dml_init_instance(&dc->dml, &dcn2_1_soc, &dcn2_1_ip, DML_PROJECT_DCN21); } /* Temporary Place holder until we can get them from fuse */ diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_mode_structs.h b/drivers/gpu/drm/amd/display/dc/dml/display_mode_structs.h index 1f5446321112..9bb8bff4cdd9 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/display_mode_structs.h +++ b/drivers/gpu/drm/amd/display/dc/dml/display_mode_structs.h @@ -25,7 +25,7 @@ #ifndef __DISPLAY_MODE_STRUCTS_H__ #define __DISPLAY_MODE_STRUCTS_H__ -#define MAX_CLOCK_LIMIT_STATES 8 +#define MAX_CLOCK_LIMIT_STATES 9 typedef struct _vcs_dpi_voltage_scaling_st voltage_scaling_st; typedef struct _vcs_dpi_soc_bounding_box_st soc_bounding_box_st; @@ -61,6 +61,7 @@ struct _vcs_dpi_voltage_scaling_st { double dram_speed_mts; double fabricclk_mhz; double dispclk_mhz; + double dram_bw_per_chan_gbps; double phyclk_mhz; double dppclk_mhz; double dtbclk_mhz; -- cgit From 32caf906187dee2f895a469f7d9f0a8e6e43e287 Mon Sep 17 00:00:00 2001 From: Yongqiang Sun Date: Wed, 22 Jan 2020 09:24:40 -0500 Subject: drm/amd/display: Check hyperV flag in DC. [Why] hyperV flag should be passed from dm to DC, and override the nv12 flip workaround flag. [How] Add flag to phy address config struct and pass the value in dm. Signed-off-by: Yongqiang Sun Reviewed-by: Tony Cheng Acked-by: Bhawanpreet Lakha Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_vm_helper.c | 3 +++ drivers/gpu/drm/amd/display/dc/dc.h | 1 + 2 files changed, 4 insertions(+) (limited to 'drivers/gpu/drm/amd/display') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_vm_helper.c b/drivers/gpu/drm/amd/display/dc/core/dc_vm_helper.c index f2b39ec35c89..64cf24a9ab08 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_vm_helper.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_vm_helper.c @@ -47,6 +47,9 @@ int dc_setup_system_context(struct dc *dc, struct dc_phy_addr_space_config *pa_c */ memcpy(&dc->vm_pa_config, pa_config, sizeof(struct dc_phy_addr_space_config)); dc->vm_pa_config.valid = true; + + if (pa_config->is_hvm_enabled == 0) + dc->debug.nv12_iflip_vm_wa = false; } return num_vmids; diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 7be2023f1a66..6f94906968b3 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -453,6 +453,7 @@ struct dc_phy_addr_space_config { } gart_config; bool valid; + bool is_hvm_enabled; uint64_t page_table_default_page_addr; }; -- cgit From c788739b8807a54b4f445f2c2854d37b61db49c2 Mon Sep 17 00:00:00 2001 From: Sung Lee Date: Thu, 23 Jan 2020 15:31:43 -0500 Subject: drm/amd/display: Add wm ranges to clk_mgr [WHY & HOW] Having watermark ranges saved inside clk_mgr to be available for debug at all times would be useful. Add it to the clk_mgr_internal struct for reference. Only populated for Renoir, unused for other asics. Signed-off-by: Sung Lee Reviewed-by: Yongqiang Sun Acked-by: Bhawanpreet Lakha Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c | 5 ++--- drivers/gpu/drm/amd/display/dc/inc/hw/clk_mgr.h | 2 ++ 2 files changed, 4 insertions(+), 3 deletions(-) (limited to 'drivers/gpu/drm/amd/display') diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c index 034a5852a416..8ecb98c29eb9 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c @@ -459,16 +459,15 @@ void build_watermark_ranges(struct clk_bw_params *bw_params, struct pp_smu_wm_ra static void rn_notify_wm_ranges(struct clk_mgr *clk_mgr_base) { struct dc_debug_options *debug = &clk_mgr_base->ctx->dc->debug; - struct pp_smu_wm_range_sets ranges = {0}; struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base); struct pp_smu_funcs *pp_smu = clk_mgr->pp_smu; if (!debug->disable_pplib_wm_range) { - build_watermark_ranges(clk_mgr_base->bw_params, &ranges); + build_watermark_ranges(clk_mgr_base->bw_params, &clk_mgr_base->ranges); /* Notify PP Lib/SMU which Watermarks to use for which clock ranges */ if (pp_smu && pp_smu->rn_funcs.set_wm_ranges) - pp_smu->rn_funcs.set_wm_ranges(&pp_smu->rn_funcs.pp_smu, &ranges); + pp_smu->rn_funcs.set_wm_ranges(&pp_smu->rn_funcs.pp_smu, &clk_mgr_base->ranges); } } diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/clk_mgr.h b/drivers/gpu/drm/amd/display/dc/inc/hw/clk_mgr.h index ac530c057ddd..ce65678c03b2 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/clk_mgr.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/clk_mgr.h @@ -27,6 +27,7 @@ #define __DAL_CLK_MGR_H__ #include "dc.h" +#include "dm_pp_smu.h" #define DCN_MINIMUM_DISPCLK_Khz 100000 #define DCN_MINIMUM_DPPCLK_Khz 100000 @@ -193,6 +194,7 @@ struct clk_mgr { int dentist_vco_freq_khz; struct clk_state_registers_and_bypass boot_snapshot; struct clk_bw_params *bw_params; + struct pp_smu_wm_range_sets ranges; }; /* forward declarations */ -- cgit From 04ad71bd146b735972134ab53540ab7955b4d1c2 Mon Sep 17 00:00:00 2001 From: David Galiffi Date: Tue, 21 Jan 2020 16:29:52 -0500 Subject: drm/amd/display: Use uint64_t logger_mask instead of uint32_t [WHY] enum dc_log_type has more than 32 entries. User cannot set larger entries, like LOG_DSC. Logs from LOG_GAMMA_DEBUG where being printed even though flag was not enabled, because dal_logger_should_log check erroneously passed. [HOW] Change struct dal_logger.mask and struct dc_init_data.mask to uint64_t. Signed-off-by: David Galiffi Reviewed-by: Tony Cheng Acked-by: Bhawanpreet Lakha Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/gpu/drm/amd/display') diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 6f94906968b3..c489a863f108 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -566,7 +566,8 @@ struct dc_init_data { struct dc_reg_helper_state *dmub_offload; struct dc_config flags; - uint32_t log_mask; + uint64_t log_mask; + /** * gpu_info FW provided soc bounding box struct or 0 if not * available in FW -- cgit From 5737f367af4840affa174562036d54eeb4288d96 Mon Sep 17 00:00:00 2001 From: Yongqiang Sun Date: Thu, 23 Jan 2020 16:30:15 -0500 Subject: drm/amd/display: Limit minimum DPPCLK to 100MHz. [Why] Underflow is observed when plug in a 4K@60 monitor with 1366x768 eDP due to DPPCLK is too low. [How] Limit minimum DPPCLK to 100MHz. Signed-off-by: Yongqiang Sun Reviewed-by: Eric Yang Acked-by: Bhawanpreet Lakha Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers/gpu/drm/amd/display') diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c index 8ecb98c29eb9..5d82ec1f1ce5 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c @@ -151,6 +151,12 @@ void rn_update_clocks(struct clk_mgr *clk_mgr_base, rn_vbios_smu_set_min_deep_sleep_dcfclk(clk_mgr, clk_mgr_base->clks.dcfclk_deep_sleep_khz); } + // workaround: Limit dppclk to 100Mhz to avoid lower eDP panel switch to plus 4K monitor underflow. + if (!IS_DIAG_DC(dc->ctx->dce_environment)) { + if (new_clocks->dppclk_khz < 100000) + new_clocks->dppclk_khz = 100000; + } + if (should_set_clock(safe_to_lower, new_clocks->dppclk_khz, clk_mgr->base.clks.dppclk_khz)) { if (clk_mgr->base.clks.dppclk_khz > new_clocks->dppclk_khz) dpp_clock_lowered = true; -- cgit From 7e1482b1c7c0d78110558d1cd31f1c1bf4209575 Mon Sep 17 00:00:00 2001 From: Aric Cyr Date: Mon, 27 Jan 2020 10:12:36 -0500 Subject: drm/amd/display: 3.2.71 Signed-off-by: Aric Cyr Reviewed-by: Aric Cyr Acked-by: Bhawanpreet Lakha Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu/drm/amd/display') diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index c489a863f108..e52a469b4672 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -39,7 +39,7 @@ #include "inc/hw/dmcu.h" #include "dml/display_mode_lib.h" -#define DC_VER "3.2.70" +#define DC_VER "3.2.71" #define MAX_SURFACES 3 #define MAX_PLANES 6 -- cgit From 60ec1b5633afaf624290c1d62145285f005634bd Mon Sep 17 00:00:00 2001 From: Nicholas Kazlauskas Date: Wed, 15 Jan 2020 14:39:52 -0500 Subject: drm/amd/display: Add DMUB tracebuffer debugfs [Why] The DMUB tracebuffer is useful for understanding DMCUB execution state. [How] Add a "show" attribute debugfs so we can loop through the buffer and print the entries. The structs for the entry format are defined in the debugfs since the tracebuffer header no longer exists in the DMUB service. Signed-off-by: Nicholas Kazlauskas Reviewed-by: Hersen Wu Acked-by: Bhawanpreet Lakha Signed-off-by: Alex Deucher --- .../drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c | 61 ++++++++++++++++++++++ 1 file changed, 61 insertions(+) (limited to 'drivers/gpu/drm/amd/display') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c index f81d3439ee8c..ead5c05eec92 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c @@ -32,6 +32,19 @@ #include "amdgpu_dm.h" #include "amdgpu_dm_debugfs.h" #include "dm_helpers.h" +#include "dmub/inc/dmub_srv.h" + +struct dmub_debugfs_trace_header { + uint32_t entry_count; + uint32_t reserved[3]; +}; + +struct dmub_debugfs_trace_entry { + uint32_t trace_code; + uint32_t tick_count; + uint32_t param0; + uint32_t param1; +}; /* function description * get/ set DP configuration: lane_count, link_rate, spread_spectrum @@ -675,6 +688,50 @@ static ssize_t dp_phy_test_pattern_debugfs_write(struct file *f, const char __us return bytes_from_user; } +/** + * Returns the DMCUB tracebuffer contents. + * Example usage: cat /sys/kernel/debug/dri/0/amdgpu_dm_dmub_tracebuffer + */ +static int dmub_tracebuffer_show(struct seq_file *m, void *data) +{ + struct amdgpu_device *adev = m->private; + struct dmub_srv_fb_info *fb_info = adev->dm.dmub_fb_info; + struct dmub_debugfs_trace_entry *entries; + uint8_t *tbuf_base; + uint32_t tbuf_size, max_entries, num_entries, i; + + if (!fb_info) + return 0; + + tbuf_base = (uint8_t *)fb_info->fb[DMUB_WINDOW_5_TRACEBUFF].cpu_addr; + if (!tbuf_base) + return 0; + + tbuf_size = fb_info->fb[DMUB_WINDOW_5_TRACEBUFF].size; + max_entries = (tbuf_size - sizeof(struct dmub_debugfs_trace_header)) / + sizeof(struct dmub_debugfs_trace_entry); + + num_entries = + ((struct dmub_debugfs_trace_header *)tbuf_base)->entry_count; + + num_entries = min(num_entries, max_entries); + + entries = (struct dmub_debugfs_trace_entry + *)(tbuf_base + + sizeof(struct dmub_debugfs_trace_header)); + + for (i = 0; i < num_entries; ++i) { + struct dmub_debugfs_trace_entry *entry = &entries[i]; + + seq_printf(m, + "trace_code=%u tick_count=%u param0=%u param1=%u\n", + entry->trace_code, entry->tick_count, entry->param0, + entry->param1); + } + + return 0; +} + /* * Returns the current and maximum output bpc for the connector. * Example usage: cat /sys/kernel/debug/dri/0/DP-1/output_bpc @@ -880,6 +937,7 @@ static ssize_t dp_dpcd_data_read(struct file *f, char __user *buf, return read_size - r; } +DEFINE_SHOW_ATTRIBUTE(dmub_tracebuffer); DEFINE_SHOW_ATTRIBUTE(output_bpc); DEFINE_SHOW_ATTRIBUTE(vrr_range); @@ -1188,5 +1246,8 @@ int dtn_debugfs_init(struct amdgpu_device *adev) debugfs_create_file_unsafe("amdgpu_dm_visual_confirm", 0644, root, adev, &visual_confirm_fops); + debugfs_create_file_unsafe("amdgpu_dm_dmub_tracebuffer", 0644, root, + adev, &dmub_tracebuffer_fops); + return 0; } -- cgit From 9edf202d27df185e04f348c30d19a63f0ebe18d8 Mon Sep 17 00:00:00 2001 From: Jing Zhou Date: Tue, 21 Jan 2020 18:05:35 +0800 Subject: drm/amd/display: external monitor abm enabled in modern standby [why] Resume from modern standby, edp stream disabled but abm keep enabled. External monitor select OTG source 0 which ABM enabled. [how] Disable abm before disable crtc when reset path mode not call core link disable stream. Signed-off-by: Jing Zhou Reviewed-by: Anthony Koo Acked-by: Bhawanpreet Lakha Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 4 ++++ drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c | 4 ++++ 2 files changed, 8 insertions(+) (limited to 'drivers/gpu/drm/amd/display') diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 7fc559acffcd..0225f8d8bb82 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -901,6 +901,10 @@ static void dcn10_reset_back_end_for_pipe( * parent pipe. */ if (pipe_ctx->top_pipe == NULL) { + + if (pipe_ctx->stream_res.abm) + pipe_ctx->stream_res.abm->funcs->set_abm_immediate_disable(pipe_ctx->stream_res.abm); + pipe_ctx->stream_res.tg->funcs->disable_crtc(pipe_ctx->stream_res.tg); pipe_ctx->stream_res.tg->funcs->enable_optc_clock(pipe_ctx->stream_res.tg, false); diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c index 52ef4d333112..b9ec40a31f5c 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c @@ -2011,6 +2011,10 @@ static void dcn20_reset_back_end_for_pipe( * parent pipe. */ if (pipe_ctx->top_pipe == NULL) { + + if (pipe_ctx->stream_res.abm) + pipe_ctx->stream_res.abm->funcs->set_abm_immediate_disable(pipe_ctx->stream_res.abm); + pipe_ctx->stream_res.tg->funcs->disable_crtc(pipe_ctx->stream_res.tg); pipe_ctx->stream_res.tg->funcs->enable_optc_clock(pipe_ctx->stream_res.tg, false); -- cgit From 96577cf82a1331732a71199522398120c649f1cf Mon Sep 17 00:00:00 2001 From: Hersen Wu Date: Tue, 14 Jan 2020 15:39:07 -0500 Subject: 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 Reviewed-by: Harry Wentland Reviewed-by: Hersen Wu Acked-by: Bhawanpreet Lakha Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 32 +++- drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c | 168 +++++++++++++++++++++ drivers/gpu/drm/amd/display/dc/dc.h | 14 ++ drivers/gpu/drm/amd/display/dc/dc_dp_types.h | 34 +++++ drivers/gpu/drm/amd/display/dc/dc_link.h | 16 ++ .../amd/display/dc/dce110/dce110_hw_sequencer.c | 14 ++ drivers/gpu/drm/amd/display/dc/inc/dc_link_dp.h | 2 + 7 files changed, 279 insertions(+), 1 deletion(-) (limited to 'drivers/gpu/drm/amd/display') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index fe50747692ec..bed57051f04d 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -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; } diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c index 07b9aa1d01af..c5b45d17e8cd 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c @@ -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; +} diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index e52a469b4672..6e2e5e24daaf 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -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" /******************************************************************************* diff --git a/drivers/gpu/drm/amd/display/dc/dc_dp_types.h b/drivers/gpu/drm/amd/display/dc/dc_dp_types.h index dfe4472c9e40..f762f35f529d 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_dp_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_dp_types.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 { diff --git a/drivers/gpu/drm/amd/display/dc/dc_link.h b/drivers/gpu/drm/amd/display/dc/dc_link.h index d25603128394..5f341e960506 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_link.h +++ b/drivers/gpu/drm/amd/display/dc/dc_link.h @@ -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); diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 56d4ec7bdad7..28b681b33f7a 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -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) diff --git a/drivers/gpu/drm/amd/display/dc/inc/dc_link_dp.h b/drivers/gpu/drm/amd/display/dc/inc/dc_link_dp.h index 8b1f0ce6c2a7..e94e5fbf2aa2 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/dc_link_dp.h +++ b/drivers/gpu/drm/amd/display/dc/inc/dc_link_dp.h @@ -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); -- cgit From 85e148fb963d27152a14e6d399a47aed9bc99c15 Mon Sep 17 00:00:00 2001 From: Tony Cheng Date: Tue, 28 Jan 2020 16:00:22 +0800 Subject: drm/amd/display: fix workaround for incorrect double buffer register for DLG ADL and TTU [Why] these registers should have been double buffered. SW workaround we will have SW program the more aggressive (lower) values whenever we are upating this register, so we will not have underflow at expense of less optimzal request pattern. [How] there is a driver bug where we don't check for 0, which is uninitialzed HW default. since 0 is smaller than any value we need to program, driver end up with not programming these registers Signed-off-by: Tony Cheng Reviewed-by: Yongqiang Sun Acked-by: Bhawanpreet Lakha Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn21/dcn21_hubp.c | 35 ++++++++++++++++------- 1 file changed, 25 insertions(+), 10 deletions(-) (limited to 'drivers/gpu/drm/amd/display') diff --git a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_hubp.c b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_hubp.c index cf09b9335728..aa7b0e7eb945 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_hubp.c +++ b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_hubp.c @@ -79,32 +79,47 @@ void apply_DEDCN21_142_wa_for_hostvm_deadline( struct _vcs_dpi_display_dlg_regs_st *dlg_attr) { struct dcn21_hubp *hubp21 = TO_DCN21_HUBP(hubp); - uint32_t cur_value; + uint32_t refcyc_per_vm_group_vblank; + uint32_t refcyc_per_vm_req_vblank; + uint32_t refcyc_per_vm_group_flip; + uint32_t refcyc_per_vm_req_flip; + const uint32_t uninitialized_hw_default = 0; - REG_GET(VBLANK_PARAMETERS_5, REFCYC_PER_VM_GROUP_VBLANK, &cur_value); - if (cur_value > dlg_attr->refcyc_per_vm_group_vblank) + REG_GET(VBLANK_PARAMETERS_5, + REFCYC_PER_VM_GROUP_VBLANK, &refcyc_per_vm_group_vblank); + + if (refcyc_per_vm_group_vblank == uninitialized_hw_default || + refcyc_per_vm_group_vblank > dlg_attr->refcyc_per_vm_group_vblank) REG_SET(VBLANK_PARAMETERS_5, 0, REFCYC_PER_VM_GROUP_VBLANK, dlg_attr->refcyc_per_vm_group_vblank); REG_GET(VBLANK_PARAMETERS_6, - REFCYC_PER_VM_REQ_VBLANK, - &cur_value); - if (cur_value > dlg_attr->refcyc_per_vm_req_vblank) + REFCYC_PER_VM_REQ_VBLANK, &refcyc_per_vm_req_vblank); + + if (refcyc_per_vm_req_vblank == uninitialized_hw_default || + refcyc_per_vm_req_vblank > dlg_attr->refcyc_per_vm_req_vblank) REG_SET(VBLANK_PARAMETERS_6, 0, REFCYC_PER_VM_REQ_VBLANK, dlg_attr->refcyc_per_vm_req_vblank); - REG_GET(FLIP_PARAMETERS_3, REFCYC_PER_VM_GROUP_FLIP, &cur_value); - if (cur_value > dlg_attr->refcyc_per_vm_group_flip) + REG_GET(FLIP_PARAMETERS_3, + REFCYC_PER_VM_GROUP_FLIP, &refcyc_per_vm_group_flip); + + if (refcyc_per_vm_group_flip == uninitialized_hw_default || + refcyc_per_vm_group_flip > dlg_attr->refcyc_per_vm_group_flip) REG_SET(FLIP_PARAMETERS_3, 0, REFCYC_PER_VM_GROUP_FLIP, dlg_attr->refcyc_per_vm_group_flip); - REG_GET(FLIP_PARAMETERS_4, REFCYC_PER_VM_REQ_FLIP, &cur_value); - if (cur_value > dlg_attr->refcyc_per_vm_req_flip) + REG_GET(FLIP_PARAMETERS_4, + REFCYC_PER_VM_REQ_FLIP, &refcyc_per_vm_req_flip); + + if (refcyc_per_vm_req_flip == uninitialized_hw_default || + refcyc_per_vm_req_flip > dlg_attr->refcyc_per_vm_req_flip) REG_SET(FLIP_PARAMETERS_4, 0, REFCYC_PER_VM_REQ_FLIP, dlg_attr->refcyc_per_vm_req_flip); REG_SET(FLIP_PARAMETERS_5, 0, REFCYC_PER_PTE_GROUP_FLIP_C, dlg_attr->refcyc_per_pte_group_flip_c); + REG_SET(FLIP_PARAMETERS_6, 0, REFCYC_PER_META_CHUNK_FLIP_C, dlg_attr->refcyc_per_meta_chunk_flip_c); } -- cgit From 15add0c2fed34adf02c8eccb399482b6e7b369bf Mon Sep 17 00:00:00 2001 From: Isabel Zhang Date: Mon, 27 Jan 2020 10:57:16 -0500 Subject: drm/amd/display: Add initialitions for PLL2 clock source [Why] Starting from 14nm, the PLL is built into the PHY and the PLL is mapped to PHY on 1 to 1 basis. In the code, the DP port is mapped to a PLL that was not initialized. This causes DP to HDMI dongle to not light up the display. [How] Initializations added for PLL2 when creating resources. Signed-off-by: Isabel Zhang Reviewed-by: Eric Yang Acked-by: Bhawanpreet Lakha Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers/gpu/drm/amd/display') diff --git a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c index 5f6fb16f16e5..e7076b0d7afb 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c @@ -60,6 +60,7 @@ #include "dcn20/dcn20_dccg.h" #include "dcn21_hubbub.h" #include "dcn10/dcn10_resource.h" +#include "dce110/dce110_resource.h" #include "dcn20/dcn20_dwb.h" #include "dcn20/dcn20_mmhubbub.h" @@ -889,6 +890,7 @@ static const struct dc_debug_options debug_defaults_diags = { enum dcn20_clk_src_array_id { DCN20_CLK_SRC_PLL0, DCN20_CLK_SRC_PLL1, + DCN20_CLK_SRC_PLL2, DCN20_CLK_SRC_TOTAL_DCN21 }; @@ -1803,6 +1805,10 @@ static bool dcn21_resource_construct( dcn21_clock_source_create(ctx, ctx->dc_bios, CLOCK_SOURCE_COMBO_PHY_PLL1, &clk_src_regs[1], false); + pool->base.clock_sources[DCN20_CLK_SRC_PLL2] = + dcn21_clock_source_create(ctx, ctx->dc_bios, + CLOCK_SOURCE_COMBO_PHY_PLL2, + &clk_src_regs[2], false); pool->base.clk_src_count = DCN20_CLK_SRC_TOTAL_DCN21; -- cgit From 896dace8eca843100bef9b7482c3d6243b4601fb Mon Sep 17 00:00:00 2001 From: Joseph Gravenor Date: Tue, 28 Jan 2020 10:38:22 -0500 Subject: drm/amd/display: turn off the mst hub before we do detection [why] not turning off the mst hub before detection on reboot causes us to not be able to light up displays with mst hook [how] on hw init, see if any displays are lit up. if so, turn them off Signed-off-by: Joseph Gravenor Reviewed-by: Eric Yang Acked-by: Bhawanpreet Lakha Signed-off-by: Alex Deucher --- .../drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) (limited to 'drivers/gpu/drm/amd/display') diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 0225f8d8bb82..42fcfee2c31b 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -48,8 +48,8 @@ #include "dc_link_dp.h" #include "dccg.h" #include "clk_mgr.h" - - +#include "link_hwss.h" +#include "dpcd_defs.h" #include "dsc.h" #define DC_LOGGER_INIT(logger) @@ -1322,6 +1322,24 @@ void dcn10_init_hw(struct dc *dc) if (hws->funcs.dsc_pg_control != NULL) hws->funcs.dsc_pg_control(hws, res_pool->dscs[i]->inst, false); + /* we want to turn off all dp displays before doing detection */ + if (dc->config.power_down_display_on_boot) { + uint8_t dpcd_power_state = '\0'; + enum dc_status status = DC_ERROR_UNEXPECTED; + + for (i = 0; i < dc->link_count; i++) { + if (dc->links[i]->connector_signal != SIGNAL_TYPE_DISPLAY_PORT) { + continue; + } + /* if any of the displays are lit up turn them off */ + status = core_link_read_dpcd(dc->links[i], DP_SET_POWER, + &dpcd_power_state, sizeof(dpcd_power_state)); + if (status == DC_OK && dpcd_power_state == DP_POWER_STATE_D0) { + dp_receiver_power_ctrl(dc->links[i], false); + } + } + } + /* If taking control over from VBIOS, we may want to optimize our first * mode set, so we need to skip powering down pipes until we know which * pipes we want to use. -- cgit From fa1d7297d09472fc4edd618196aad27281ba2644 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 28 Nov 2019 09:27:14 +0100 Subject: drm/amd/display: Fix wrongly passed static prefix MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently, gcc spews a warning as: drivers/gpu/drm/amd/amdgpu/../display/dc/dcn10/dcn10_hubbub.c: In function ‘hubbub1_verify_allow_pstate_change_high’: ./include/drm/drm_print.h:316:2: warning: ‘debug_data’ may be used uninitialized in this function [-Wmaybe-uninitialized] This is because the code checks against a static value although it's basically a constant and guaranteed to be set. This patch changes the type prefix from static to const for addressing the compile warning above and also for letting the compiler optimize better. Fixes: 62d591a8e00c ("drm/amd/display: create new files for hubbub functions") Reviewed-by: Harry Wentland Signed-off-by: Takashi Iwai Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubbub.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/gpu/drm/amd/display') diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubbub.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubbub.c index 870735deaca7..3e851713cf8d 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubbub.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubbub.c @@ -128,8 +128,8 @@ bool hubbub1_verify_allow_pstate_change_high( * pstate takes around ~100us on linux. Unknown currently as to * why it takes that long on linux */ - static unsigned int pstate_wait_timeout_us = 200; - static unsigned int pstate_wait_expected_timeout_us = 40; + const unsigned int pstate_wait_timeout_us = 200; + const unsigned int pstate_wait_expected_timeout_us = 40; static unsigned int max_sampled_pstate_wait_us; /* data collection */ static bool forced_pstate_allow; /* help with revert wa */ -- cgit From f9f3e9e0136b4b89128d8384eb9410381b10c305 Mon Sep 17 00:00:00 2001 From: Daniel Kolesa Date: Thu, 6 Feb 2020 20:14:35 +0100 Subject: amdgpu: Prevent build errors regarding soft/hard-float FP ABI tags On PowerPC, the compiler will tag object files with whether they use hard or soft float FP ABI and whether they use 64 or 128-bit long double ABI. On systems with 64-bit long double ABI, a tag will get emitted whenever a double is used, as on those systems a long double is the same as a double. This will prevent linkage as other files are being compiled with hard-float. On ppc64, this code will never actually get used for the time being, as the only currently existing hardware using it are the Renoir APUs. Therefore, until this is testable and can be fixed properly, at least make sure the build will not fail. Signed-off-by: Daniel Kolesa Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/clk_mgr/Makefile | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers/gpu/drm/amd/display') diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/Makefile b/drivers/gpu/drm/amd/display/dc/clk_mgr/Makefile index 3cd283195091..c0f6a8c7de7d 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/Makefile +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/Makefile @@ -87,6 +87,12 @@ AMD_DISPLAY_FILES += $(AMD_DAL_CLK_MGR_DCN20) ############################################################################### CLK_MGR_DCN21 = rn_clk_mgr.o rn_clk_mgr_vbios_smu.o +# prevent build errors regarding soft-float vs hard-float FP ABI tags +# this code is currently unused on ppc64, as it applies to Renoir APUs only +ifdef CONFIG_PPC64 +CFLAGS_$(AMDDALPATH)/dc/clk_mgr/dcn21/rn_clk_mgr.o := $(call cc-option,-mno-gnu-attribute) +endif + AMD_DAL_CLK_MGR_DCN21 = $(addprefix $(AMDDALPATH)/dc/clk_mgr/dcn21/,$(CLK_MGR_DCN21)) AMD_DISPLAY_FILES += $(AMD_DAL_CLK_MGR_DCN21) -- cgit From cb8348fec250e517b5facb4cab3125ddc597f9aa Mon Sep 17 00:00:00 2001 From: Martin Leung Date: Tue, 28 Jan 2020 11:58:44 -0500 Subject: drm/amd/display: always apply T7/T9 delay logic [why] before we exit early in edp_reciever_ready if we detect that panel is not edp or below rev 1.2. This will skip the backlight/t7 delay panel patch. [how] edit logic to ensure panel patch is applied regardless of edp rev. Signed-off-by: Martin Leung Reviewed-by: Anthony Koo Acked-by: Rodrigo Siqueira Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c | 56 +++++++++++----------- 1 file changed, 29 insertions(+), 27 deletions(-) (limited to 'drivers/gpu/drm/amd/display') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c index ddb855045767..58634f191a55 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c @@ -153,18 +153,19 @@ bool edp_receiver_ready_T9(struct dc_link *link) unsigned char edpRev = 0; enum dc_status result = DC_OK; result = core_link_read_dpcd(link, DP_EDP_DPCD_REV, &edpRev, sizeof(edpRev)); - if (edpRev < DP_EDP_12) - return true; - /* start from eDP version 1.2, SINK_STAUS indicate the sink is ready.*/ - do { - sinkstatus = 1; - result = core_link_read_dpcd(link, DP_SINK_STATUS, &sinkstatus, sizeof(sinkstatus)); - if (sinkstatus == 0) - break; - if (result != DC_OK) - break; - udelay(100); //MAx T9 - } while (++tries < 50); + + /* start from eDP version 1.2, SINK_STAUS indicate the sink is ready.*/ + if (result == DC_OK && edpRev >= DP_EDP_12) { + do { + sinkstatus = 1; + result = core_link_read_dpcd(link, DP_SINK_STATUS, &sinkstatus, sizeof(sinkstatus)); + if (sinkstatus == 0) + break; + if (result != DC_OK) + break; + udelay(100); //MAx T9 + } while (++tries < 50); + } if (link->local_sink->edid_caps.panel_patch.extra_delay_backlight_off > 0) udelay(link->local_sink->edid_caps.panel_patch.extra_delay_backlight_off * 1000); @@ -183,21 +184,22 @@ bool edp_receiver_ready_T7(struct dc_link *link) unsigned long long time_taken_in_ns = 0; result = core_link_read_dpcd(link, DP_EDP_DPCD_REV, &edpRev, sizeof(edpRev)); - if (result == DC_OK && edpRev < DP_EDP_12) - return true; - /* start from eDP version 1.2, SINK_STAUS indicate the sink is ready.*/ - enter_timestamp = dm_get_timestamp(link->ctx); - do { - sinkstatus = 0; - result = core_link_read_dpcd(link, DP_SINK_STATUS, &sinkstatus, sizeof(sinkstatus)); - if (sinkstatus == 1) - break; - if (result != DC_OK) - break; - udelay(25); - finish_timestamp = dm_get_timestamp(link->ctx); - time_taken_in_ns = dm_get_elapse_time_in_ns(link->ctx, finish_timestamp, enter_timestamp); - } while (time_taken_in_ns < 50 * 1000000); //MAx T7 is 50ms + + if (result == DC_OK && edpRev >= DP_EDP_12) { + /* start from eDP version 1.2, SINK_STAUS indicate the sink is ready.*/ + enter_timestamp = dm_get_timestamp(link->ctx); + do { + sinkstatus = 0; + result = core_link_read_dpcd(link, DP_SINK_STATUS, &sinkstatus, sizeof(sinkstatus)); + if (sinkstatus == 1) + break; + if (result != DC_OK) + break; + udelay(25); + finish_timestamp = dm_get_timestamp(link->ctx); + time_taken_in_ns = dm_get_elapse_time_in_ns(link->ctx, finish_timestamp, enter_timestamp); + } while (time_taken_in_ns < 50 * 1000000); //MAx T7 is 50ms + } if (link->local_sink->edid_caps.panel_patch.extra_t7_ms > 0) udelay(link->local_sink->edid_caps.panel_patch.extra_t7_ms * 1000); -- cgit From bd2d7067ef78a203235981071af419223025fe77 Mon Sep 17 00:00:00 2001 From: Nicholas Kazlauskas Date: Sat, 18 Jan 2020 15:23:49 -0500 Subject: drm/amd/display: Don't treat missing command table as failure [Why] With the fallback case in place for command table offloading via DMCUB it's no longer an error for the command table to be missing specific entries. [How] Drop the BREAK_TO_DEBUGGER(); Signed-off-by: Nicholas Kazlauskas Reviewed-by: Chris Park Acked-by: Rodrigo Siqueira Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/bios/command_table2.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/gpu/drm/amd/display') diff --git a/drivers/gpu/drm/amd/display/dc/bios/command_table2.c b/drivers/gpu/drm/amd/display/dc/bios/command_table2.c index 629a07a2719b..c38f75a56129 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/command_table2.c +++ b/drivers/gpu/drm/amd/display/dc/bios/command_table2.c @@ -221,8 +221,8 @@ static void init_transmitter_control(struct bios_parser *bp) uint8_t frev; uint8_t crev; - if (BIOS_CMD_TABLE_REVISION(dig1transmittercontrol, frev, crev) == false) - BREAK_TO_DEBUGGER(); + BIOS_CMD_TABLE_REVISION(dig1transmittercontrol, frev, crev); + switch (crev) { case 6: bp->cmd_tbl.transmitter_control = transmitter_control_v1_6; -- cgit From 5c4a6d6297b0767c00d66349627b3c2f0d7866a7 Mon Sep 17 00:00:00 2001 From: Wyatt Wood Date: Wed, 15 Jan 2020 14:16:12 -0500 Subject: drm/amd/display: Remove unused values from psr struct [Why] Taking up unnecessary space. [How] Remove unused values from psr struct. Signed-off-by: Wyatt Wood Reviewed-by: Nicholas Kazlauskas Acked-by: Rodrigo Siqueira Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce/dmub_psr.c | 13 ------------- drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h | 10 ---------- 2 files changed, 23 deletions(-) (limited to 'drivers/gpu/drm/amd/display') diff --git a/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.c b/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.c index bdf80b09277e..59cdd8ea31fb 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.c @@ -159,10 +159,6 @@ static bool dmub_psr_copy_settings(struct dmub_psr *dmub, copy_settings_data->mpcc_inst = pipe_ctx->plane_res.mpcc_inst; - if (pipe_ctx->plane_res.hubp) - copy_settings_data->hubp_inst = pipe_ctx->plane_res.hubp->inst; - else - copy_settings_data->hubp_inst = 0; if (pipe_ctx->plane_res.dpp) copy_settings_data->dpp_inst = pipe_ctx->plane_res.dpp->inst; else @@ -178,18 +174,9 @@ static bool dmub_psr_copy_settings(struct dmub_psr *dmub, // Misc copy_settings_data->psr_level = psr_context->psr_level.u32all; - copy_settings_data->hyst_frames = psr_context->timehyst_frames; - copy_settings_data->hyst_lines = psr_context->hyst_lines; - copy_settings_data->phy_type = psr_context->phyType; - copy_settings_data->aux_repeat = psr_context->aux_repeats; copy_settings_data->smu_optimizations_en = psr_context->allow_smu_optimizations; - copy_settings_data->skip_wait_for_pll_lock = psr_context->skipPsrWaitForPllLock; copy_settings_data->frame_delay = psr_context->frame_delay; - copy_settings_data->smu_phy_id = psr_context->smuPhyId; - copy_settings_data->num_of_controllers = psr_context->numberOfControllers; copy_settings_data->frame_cap_ind = psr_context->psrFrameCaptureIndicationReq; - copy_settings_data->phy_num = psr_context->frame_delay & 0x7; - copy_settings_data->link_rate = psr_context->frame_delay & 0xF; dc_dmub_srv_cmd_queue(dc->dmub_srv, &cmd.psr_copy_settings.header); dc_dmub_srv_cmd_execute(dc->dmub_srv); diff --git a/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h b/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h index 8f518e7d8b4e..0cb8967f0c45 100644 --- a/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h +++ b/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h @@ -216,7 +216,6 @@ struct dmub_rb_cmd_dpphy_init { struct dmub_cmd_psr_copy_settings_data { uint16_t psr_level; - uint8_t hubp_inst; uint8_t dpp_inst; uint8_t mpcc_inst; uint8_t opp_inst; @@ -225,17 +224,8 @@ struct dmub_cmd_psr_copy_settings_data { uint8_t digbe_inst; uint8_t dpphy_inst; uint8_t aux_inst; - uint8_t hyst_frames; - uint8_t hyst_lines; - uint8_t phy_num; - uint8_t phy_type; - uint8_t aux_repeat; uint8_t smu_optimizations_en; - uint8_t skip_wait_for_pll_lock; uint8_t frame_delay; - uint8_t smu_phy_id; - uint8_t num_of_controllers; - uint8_t link_rate; uint8_t frame_cap_ind; }; -- cgit From 0136684f9b58b78fb2b8671e8eaa7bfc41330e0f Mon Sep 17 00:00:00 2001 From: Calvin Hou Date: Mon, 27 Jan 2020 14:40:41 -0500 Subject: drm/amd/display: Pass override OUI in to dc_init_data [WHY] Vendor dongle requires propietary OUI and handshake sequence. [HOW] Add a new structure to dc_init_data, to allow creator to pass an override vendor_oui. This value will be written to DP_SOURCE_OUI instead of AMD signature, when dpcd_set_source_specific_data is called. Signed-off-by: Calvin Hou Reviewed-by: Jun Lei Acked-by: Rodrigo Siqueira Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 2 +- drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c | 41 ++++++++++++++---------- drivers/gpu/drm/amd/display/dc/dc.h | 2 ++ drivers/gpu/drm/amd/display/dc/dc_dp_types.h | 14 ++++++++ 4 files changed, 41 insertions(+), 18 deletions(-) (limited to 'drivers/gpu/drm/amd/display') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 40878b86a05d..7513aa71da38 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -701,7 +701,7 @@ static bool dc_construct(struct dc *dc, dc_ctx->created_bios = true; } - + dc->vendor_signature = init_params->vendor_signature; /* Create GPIO service */ dc_ctx->gpio_service = dal_gpio_service_create( diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c index c5b45d17e8cd..3bc05fa93ed5 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c @@ -4179,25 +4179,32 @@ 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)); + if (!link->dc->vendor_signature.is_valid) { + struct dpcd_amd_signature amd_signature; + 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)); + + } else { + core_link_write_dpcd(link, DP_SOURCE_OUI, + link->dc->vendor_signature.data.raw, + sizeof(link->dc->vendor_signature.data.raw)); + } // Sink may need to configure internals based on vendor, so allow some // time before proceeding with possibly vendor specific transactions diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 6e2e5e24daaf..8c88706040a7 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -527,6 +527,7 @@ struct dc { struct compressor *fbc_compressor; struct dc_debug_data debug_data; + struct dpcd_vendor_signature vendor_signature; const char *build_id; struct vm_helper *vm_helper; @@ -573,6 +574,7 @@ struct dc_init_data { * available in FW */ const struct gpu_info_soc_bounding_box_v1_0 *soc_bounding_box; + struct dpcd_vendor_signature vendor_signature; }; struct dc_callback_init { diff --git a/drivers/gpu/drm/amd/display/dc/dc_dp_types.h b/drivers/gpu/drm/amd/display/dc/dc_dp_types.h index f762f35f529d..bb2730e9521e 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_dp_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_dp_types.h @@ -432,6 +432,20 @@ struct dp_sink_hw_fw_revision { uint8_t ieee_fw_rev[2]; }; +struct dpcd_vendor_signature { + bool is_valid; + + union dpcd_ieee_vendor_signature { + struct { + uint8_t ieee_oui[3];/*24-bit IEEE OUI*/ + uint8_t ieee_device_id[6];/*usually 6-byte ASCII name*/ + uint8_t ieee_hw_rev; + uint8_t ieee_fw_rev[2]; + }; + uint8_t raw[12]; + } data; +}; + struct dpcd_amd_signature { uint8_t AMD_IEEE_TxSignature_byte1; uint8_t AMD_IEEE_TxSignature_byte2; -- cgit From 8eb85cb5ada1e9b760041fb1ccb61086038770af Mon Sep 17 00:00:00 2001 From: Wyatt Wood Date: Thu, 16 Jan 2020 17:53:09 -0500 Subject: drm/amd/display: Hookup psr set version call [Why] Set version is currently not called. [How] Add call to set version from copy settings. This should be the only time this is called as the eDP caps should never change. Signed-off-by: Wyatt Wood Reviewed-by: Nicholas Kazlauskas Acked-by: Rodrigo Siqueira Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce/dmub_psr.c | 17 ++++++++++++----- drivers/gpu/drm/amd/display/dc/dce/dmub_psr.h | 1 - 2 files changed, 12 insertions(+), 6 deletions(-) (limited to 'drivers/gpu/drm/amd/display') diff --git a/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.c b/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.c index 59cdd8ea31fb..cacb46979f31 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.c @@ -42,17 +42,19 @@ static void dmub_psr_get_state(uint32_t *psr_state) // Trigger GPINT interrupt from firmware } -static void dmub_psr_set_version(struct dmub_psr *dmub, struct dc_stream_state *stream) +/** + * Set PSR version. + */ +static bool dmub_psr_set_version(struct dmub_psr *dmub, struct dc_stream_state *stream) { - //stream->psr_version; union dmub_rb_cmd cmd; struct dc_context *dc = dmub->ctx; cmd.psr_set_version.header.type = DMUB_CMD__PSR; cmd.psr_set_version.header.sub_type = DMUB_CMD__PSR_SET_VERSION; - if (stream->psr_version == 0x0) - return; + if (stream->psr_version == 0x0) // Unsupported + return false; else if (stream->psr_version == 0x1) cmd.psr_set_version.psr_set_version_data.version = PSR_VERSION_1; else if (stream->psr_version == 0x2) @@ -63,6 +65,8 @@ static void dmub_psr_set_version(struct dmub_psr *dmub, struct dc_stream_state * dc_dmub_srv_cmd_queue(dc->dmub_srv, &cmd.psr_enable.header); dc_dmub_srv_cmd_execute(dc->dmub_srv); dc_dmub_srv_wait_idle(dc->dmub_srv); + + return true; } /** @@ -139,6 +143,10 @@ static bool dmub_psr_copy_settings(struct dmub_psr *dmub, if (!pipe_ctx || !&pipe_ctx->plane_res || !&pipe_ctx->stream_res) return false; + // First, set the psr version + if (!dmub_psr_set_version(dmub, pipe_ctx->stream)) + return false; + // Program DP DPHY fast training registers link->link_enc->funcs->psr_program_dp_dphy_fast_training(link->link_enc, psr_context->psrExitLinkTrainingRequired); @@ -186,7 +194,6 @@ static bool dmub_psr_copy_settings(struct dmub_psr *dmub, } static const struct dmub_psr_funcs psr_funcs = { - .psr_set_version = dmub_psr_set_version, .psr_copy_settings = dmub_psr_copy_settings, .psr_enable = dmub_psr_enable, .psr_get_state = dmub_psr_get_state, diff --git a/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.h b/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.h index 4fe8b53d9551..5e8553d450c9 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.h @@ -34,7 +34,6 @@ struct dmub_psr { }; struct dmub_psr_funcs { - void (*psr_set_version)(struct dmub_psr *dmub, struct dc_stream_state *stream); bool (*psr_copy_settings)(struct dmub_psr *dmub, struct dc_link *link, struct psr_context *psr_context); void (*psr_enable)(struct dmub_psr *dmub, bool enable); void (*psr_get_state)(uint32_t *psr_state); -- cgit From 8a683eb6311a03b655ab8ff368cd7b203074275c Mon Sep 17 00:00:00 2001 From: Rodrigo Siqueira Date: Tue, 28 Jan 2020 18:01:48 -0500 Subject: drm/amd/display: Add AUX backlight register Introduce vendor-specific registers for handling backlight via AUX. Signed-off-by: Rodrigo Siqueira Reviewed-by: Nicholas Kazlauskas Acked-by: Harry Wentland Acked-by: Rodrigo Siqueira Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c | 8 -------- drivers/gpu/drm/amd/display/include/dpcd_defs.h | 8 ++++++++ 2 files changed, 8 insertions(+), 8 deletions(-) (limited to 'drivers/gpu/drm/amd/display') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c index 3bc05fa93ed5..c0fcee4b5b69 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c @@ -20,14 +20,6 @@ #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, diff --git a/drivers/gpu/drm/amd/display/include/dpcd_defs.h b/drivers/gpu/drm/amd/display/include/dpcd_defs.h index 2c90d1b46c8b..3d29646c7cb4 100644 --- a/drivers/gpu/drm/amd/display/include/dpcd_defs.h +++ b/drivers/gpu/drm/amd/display/include/dpcd_defs.h @@ -149,4 +149,12 @@ enum dpcd_psr_sink_states { PSR_SINK_STATE_SINK_INTERNAL_ERROR = 7, }; +#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 + #endif /* __DAL_DPCD_DEFS_H__ */ -- cgit From 945628101be55833a63355510d4b6c934183deab Mon Sep 17 00:00:00 2001 From: Rodrigo Siqueira Date: Fri, 24 Jan 2020 10:44:20 -0500 Subject: drm/amd/display: Add backlight support via AUX Several modern displays support HDR/OLED panel, and one of the interesting changes provided by this technology is the new approach for handling backlight. More precisely, in the traditional way, we use PWM to manage display backlight; however, with HDR/OLED we begin to use DP Aux channel for adjusting the backlight. This patch, enable the backlight control in HDR/OLED display via DP Aux. Signed-off-by: Rodrigo Siqueira Reviewed-by: Harry Wentland Acked-by: Rodrigo Siqueira Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 161 ++++++++++++++++++---- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h | 34 ++++- 2 files changed, 167 insertions(+), 28 deletions(-) (limited to 'drivers/gpu/drm/amd/display') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index bd798b6bdf0f..f4e4c42341b9 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -1758,6 +1758,61 @@ static struct drm_mode_config_helper_funcs amdgpu_dm_mode_config_helperfuncs = { .atomic_commit_tail = amdgpu_dm_atomic_commit_tail }; +static void update_connector_ext_caps(struct amdgpu_dm_connector *aconnector) +{ + u32 max_cll, min_cll, max, min, q, r; + struct amdgpu_dm_backlight_caps *caps; + struct amdgpu_display_manager *dm; + struct drm_connector *conn_base; + struct amdgpu_device *adev; + static const u8 pre_computed_values[] = { + 50, 51, 52, 53, 55, 56, 57, 58, 59, 61, 62, 63, 65, 66, 68, 69, + 71, 72, 74, 75, 77, 79, 81, 82, 84, 86, 88, 90, 92, 94, 96, 98}; + + if (!aconnector || !aconnector->dc_link) + return; + + conn_base = &aconnector->base; + adev = conn_base->dev->dev_private; + dm = &adev->dm; + caps = &dm->backlight_caps; + caps->ext_caps = &aconnector->dc_link->dpcd_sink_ext_caps; + caps->aux_support = false; + max_cll = conn_base->hdr_sink_metadata.hdmi_type1.max_cll; + min_cll = conn_base->hdr_sink_metadata.hdmi_type1.min_cll; + + 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; + + /* From the specification (CTA-861-G), for calculating the maximum + * luminance we need to use: + * Luminance = 50*2**(CV/32) + * Where CV is a one-byte value. + * For calculating this expression we may need float point precision; + * to avoid this complexity level, we take advantage that CV is divided + * by a constant. From the Euclids division algorithm, we know that CV + * can be written as: CV = 32*q + r. Next, we replace CV in the + * Luminance expression and get 50*(2**q)*(2**(r/32)), hence we just + * need to pre-compute the value of r/32. For pre-computing the values + * We just used the following Ruby line: + * (0...32).each {|cv| puts (50*2**(cv/32.0)).round} + * The results of the above expressions can be verified at + * pre_computed_values. + */ + q = max_cll >> 5; + r = max_cll % 32; + max = (1 << q) * pre_computed_values[r]; + + // min luminance: maxLum * (CV/255)^2 / 100 + q = DIV_ROUND_CLOSEST(min_cll, 255); + min = max * DIV_ROUND_CLOSEST((q * q), 100); + + caps->aux_max_input_signal = max; + caps->aux_min_input_signal = min; +} + static void amdgpu_dm_update_connector_after_detect(struct amdgpu_dm_connector *aconnector) { @@ -1872,7 +1927,7 @@ amdgpu_dm_update_connector_after_detect(struct amdgpu_dm_connector *aconnector) aconnector->edid); } amdgpu_dm_update_freesync_caps(connector, aconnector->edid); - + update_connector_ext_caps(aconnector); } else { drm_dp_cec_unset_edid(&aconnector->dm_dp_aux.aux); amdgpu_dm_update_freesync_caps(connector, NULL); @@ -2484,6 +2539,7 @@ static int amdgpu_dm_mode_config_init(struct amdgpu_device *adev) #define AMDGPU_DM_DEFAULT_MIN_BACKLIGHT 12 #define AMDGPU_DM_DEFAULT_MAX_BACKLIGHT 255 +#define AUX_BL_DEFAULT_TRANSITION_TIME_MS 50 #if defined(CONFIG_BACKLIGHT_CLASS_DEVICE) ||\ defined(CONFIG_BACKLIGHT_CLASS_DEVICE_MODULE) @@ -2498,9 +2554,11 @@ static void amdgpu_dm_update_backlight_caps(struct amdgpu_display_manager *dm) amdgpu_acpi_get_backlight_caps(dm->adev, &caps); if (caps.caps_valid) { + dm->backlight_caps.caps_valid = true; + if (caps.aux_support) + return; dm->backlight_caps.min_input_signal = caps.min_input_signal; dm->backlight_caps.max_input_signal = caps.max_input_signal; - dm->backlight_caps.caps_valid = true; } else { dm->backlight_caps.min_input_signal = AMDGPU_DM_DEFAULT_MIN_BACKLIGHT; @@ -2508,40 +2566,95 @@ static void amdgpu_dm_update_backlight_caps(struct amdgpu_display_manager *dm) AMDGPU_DM_DEFAULT_MAX_BACKLIGHT; } #else + if (dm->backlight_caps.aux_support) + return; + dm->backlight_caps.min_input_signal = AMDGPU_DM_DEFAULT_MIN_BACKLIGHT; dm->backlight_caps.max_input_signal = AMDGPU_DM_DEFAULT_MAX_BACKLIGHT; #endif } +static int set_backlight_via_aux(struct dc_link *link, uint32_t brightness) +{ + bool rc; + + if (!link) + return 1; + + rc = dc_link_set_backlight_level_nits(link, true, brightness, + AUX_BL_DEFAULT_TRANSITION_TIME_MS); + + return rc ? 0 : 1; +} + +static u32 convert_brightness(const struct amdgpu_dm_backlight_caps *caps, + const uint32_t user_brightness) +{ + u32 min, max, conversion_pace; + u32 brightness = user_brightness; + + if (!caps) + goto out; + + if (!caps->aux_support) { + max = caps->max_input_signal; + min = caps->min_input_signal; + /* + * The brightness input is in the range 0-255 + * It needs to be rescaled to be between the + * requested min and max input signal + * It also needs to be scaled up by 0x101 to + * match the DC interface which has a range of + * 0 to 0xffff + */ + conversion_pace = 0x101; + brightness = + user_brightness + * conversion_pace + * (max - min) + / AMDGPU_MAX_BL_LEVEL + + min * conversion_pace; + } else { + /* TODO + * We are doing a linear interpolation here, which is OK but + * does not provide the optimal result. We probably want + * something close to the Perceptual Quantizer (PQ) curve. + */ + max = caps->aux_max_input_signal; + min = caps->aux_min_input_signal; + + brightness = (AMDGPU_MAX_BL_LEVEL - user_brightness) * min + + user_brightness * max; + // Multiple the value by 1000 since we use millinits + brightness *= 1000; + brightness = DIV_ROUND_CLOSEST(brightness, AMDGPU_MAX_BL_LEVEL); + } + +out: + return brightness; +} + static int amdgpu_dm_backlight_update_status(struct backlight_device *bd) { struct amdgpu_display_manager *dm = bl_get_data(bd); struct amdgpu_dm_backlight_caps caps; - uint32_t brightness = bd->props.brightness; + struct dc_link *link = NULL; + u32 brightness; + bool rc; amdgpu_dm_update_backlight_caps(dm); caps = dm->backlight_caps; - /* - * The brightness input is in the range 0-255 - * It needs to be rescaled to be between the - * requested min and max input signal - * - * It also needs to be scaled up by 0x101 to - * match the DC interface which has a range of - * 0 to 0xffff - */ - brightness = - brightness - * 0x101 - * (caps.max_input_signal - caps.min_input_signal) - / AMDGPU_MAX_BL_LEVEL - + caps.min_input_signal * 0x101; - - if (dc_link_set_backlight_level(dm->backlight_link, - brightness, 0)) - return 0; - else - return 1; + + link = (struct dc_link *)dm->backlight_link; + + brightness = convert_brightness(&caps, bd->props.brightness); + // Change brightness based on AUX property + if (caps.aux_support) + return set_backlight_via_aux(link, brightness); + + rc = dc_link_set_backlight_level(dm->backlight_link, brightness, 0); + + return rc ? 0 : 1; } static int amdgpu_dm_backlight_get_brightness(struct backlight_device *bd) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h index 7ea9acb0358d..2bec5e6a3054 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h @@ -90,15 +90,41 @@ struct dm_comressor_info { }; /** - * struct amdgpu_dm_backlight_caps - Usable range of backlight values from ACPI - * @min_input_signal: minimum possible input in range 0-255 - * @max_input_signal: maximum possible input in range 0-255 - * @caps_valid: true if these values are from the ACPI interface + * struct amdgpu_dm_backlight_caps - Information about backlight + * + * Describe the backlight support for ACPI or eDP AUX. */ struct amdgpu_dm_backlight_caps { + /** + * @ext_caps: Keep the data struct with all the information about the + * display support for HDR. + */ + union dpcd_sink_ext_caps *ext_caps; + /** + * @aux_min_input_signal: Min brightness value supported by the display + */ + u32 aux_min_input_signal; + /** + * @aux_max_input_signal: Max brightness value supported by the display + * in nits. + */ + u32 aux_max_input_signal; + /** + * @min_input_signal: minimum possible input in range 0-255. + */ int min_input_signal; + /** + * @max_input_signal: maximum possible input in range 0-255. + */ int max_input_signal; + /** + * @caps_valid: true if these values are from the ACPI interface. + */ bool caps_valid; + /** + * @aux_support: Describes if the display supports AUX backlight. + */ + bool aux_support; }; /** -- cgit From 7ba99b43be6527eb9bdbf137e6829d4ec4b871c6 Mon Sep 17 00:00:00 2001 From: Peikang Zhang Date: Thu, 30 Jan 2020 10:49:46 -0500 Subject: drm/amd/display: Toggle VSR button cause system crash [Why] in dcn10_apply_ctx_for_surface(), if we hit !top_pipe_to_program, pipe_ctx->update_flags could not get cleared. [How] Moved clearing pipe_ctx->update_flags logic before if (!top_pipe_to_program) to gurantee pipe_ctx->update_flags get cleared. Signed-off-by: Peikang Zhang Reviewed-by: Aric Cyr Acked-by: Rodrigo Siqueira Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'drivers/gpu/drm/amd/display') diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 42fcfee2c31b..87e30f60cee6 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -2540,6 +2540,12 @@ void dcn10_apply_ctx_for_surface( dcn10_find_top_pipe_for_stream(dc, context, stream); DC_LOGGER_INIT(dc->ctx->logger); + // Clear pipe_ctx flag + for (i = 0; i < dc->res_pool->pipe_count; i++) { + struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; + pipe_ctx->update_flags.raw = 0; + } + if (!top_pipe_to_program) return; @@ -2570,8 +2576,6 @@ void dcn10_apply_ctx_for_surface( struct pipe_ctx *old_pipe_ctx = &dc->current_state->res_ctx.pipe_ctx[i]; - pipe_ctx->update_flags.raw = 0; - if ((!pipe_ctx->plane_state || pipe_ctx->stream_res.tg != old_pipe_ctx->stream_res.tg) && old_pipe_ctx->plane_state && -- cgit From 710e0cede86180ddc718cbb2ee7f7f9ba29a704a Mon Sep 17 00:00:00 2001 From: Anthony Koo Date: Thu, 30 Jan 2020 16:47:45 -0500 Subject: drm/amd/display: Update register defines [Why] Some register defines are redundant or updated [How] Update register defines Remove some redundant defines Signed-off-by: Anthony Koo Reviewed-by: Wyatt Wood Acked-by: Rodrigo Siqueira Acked-by: Sun peng Li Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/dcn20/dcn20_mmhubbub.h | 20 -------------------- drivers/gpu/drm/amd/display/dc/dcn20/dcn20_vmid.h | 7 ------- 2 files changed, 27 deletions(-) (limited to 'drivers/gpu/drm/amd/display') diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_mmhubbub.h b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_mmhubbub.h index 3fccd5eeecbb..7bcee5894d2e 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_mmhubbub.h +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_mmhubbub.h @@ -36,26 +36,6 @@ #define BASE(seg) \ BASE_INNER(seg) -#define SR(reg_name)\ - .reg_name = BASE(mm ## reg_name ## _BASE_IDX) + \ - mm ## reg_name - -#define SRI(reg_name, block, id)\ - .reg_name = BASE(mm ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ - mm ## block ## id ## _ ## reg_name - -#define SRI2(reg_name, block, id)\ - .reg_name = BASE(mm ## reg_name ## _BASE_IDX) + \ - mm ## reg_name - -#define SRII(reg_name, block, id)\ - .reg_name[id] = BASE(mm ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ - mm ## block ## id ## _ ## reg_name - -#define SF(reg_name, field_name, post_fix)\ - .field_name = reg_name ## __ ## field_name ## post_fix - - #define MCIF_WB_COMMON_REG_LIST_DCN2_0(inst) \ SRI(MCIF_WB_BUFMGR_SW_CONTROL, MCIF_WB, inst),\ SRI(MCIF_WB_BUFMGR_CUR_LINE_R, MCIF_WB, inst),\ diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_vmid.h b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_vmid.h index 02fafb013fc6..f1ef46e8da5b 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_vmid.h +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_vmid.h @@ -34,13 +34,6 @@ #define BASE(seg) \ BASE_INNER(seg) -#define SRI(reg_name, block, id)\ - .reg_name = BASE(mm ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ - mm ## block ## id ## _ ## reg_name - -#define SF(reg_name, field_name, post_fix)\ - .field_name = reg_name ## __ ## field_name ## post_fix - #define DCN20_VMID_REG_LIST(id)\ SRI(CNTL, DCN_VM_CONTEXT, id),\ SRI(PAGE_TABLE_BASE_ADDR_HI32, DCN_VM_CONTEXT, id),\ -- cgit From 5a33b037f045102b40a93eb73759efdc0e924eea Mon Sep 17 00:00:00 2001 From: Nikola Cornij Date: Tue, 28 Jan 2020 14:05:02 -0500 Subject: drm/amd/display: Drop unused field from dc_panel_patch In the struct dc_panel_patch, we have a field named manage_secondary_link which is not used by any part of the code. This commit drops the unused field. Signed-off-by: Nikola Cornij Reviewed-by: Joshua Aberback Acked-by: Rodrigo Siqueira Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc_types.h | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/gpu/drm/amd/display') diff --git a/drivers/gpu/drm/amd/display/dc/dc_types.h b/drivers/gpu/drm/amd/display/dc/dc_types.h index e59532d98cb4..122c96455792 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_types.h @@ -229,7 +229,6 @@ struct dc_panel_patch { unsigned int extra_t12_ms; unsigned int extra_delay_backlight_off; unsigned int extra_t7_ms; - unsigned int manage_secondary_link; }; struct dc_edid_caps { -- cgit From 97f1fbda21c4de7686b04c27a95e4db9f3035484 Mon Sep 17 00:00:00 2001 From: Anthony Koo Date: Sun, 2 Feb 2020 11:51:54 -0500 Subject: drm/amd/display: 3.2.72 Signed-off-by: Anthony Koo Reviewed-by: Anthony Koo Acked-by: Rodrigo Siqueira Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu/drm/amd/display') diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 8c88706040a7..f77b3acfeb06 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -39,7 +39,7 @@ #include "inc/hw/dmcu.h" #include "dml/display_mode_lib.h" -#define DC_VER "3.2.71" +#define DC_VER "3.2.72" #define MAX_SURFACES 3 #define MAX_PLANES 6 -- cgit From 5bf24270d1ccd94f0b6efcd7c96b98bf1faea893 Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Fri, 13 Dec 2019 18:22:40 -0500 Subject: drm/amd/display: add odm split logic to scaling calculations Currently odm scaling calculations are only done when adding initial odm pipe. Any scaling re-calculations will mess up odm because of this. This change resolves the problem by updating scaling split logic to handle odm. Signed-off-by: Dmytro Laktyushkin Reviewed-by: Eric Yang Acked-by: Michael Strauss Acked-by: Rodrigo Siqueira Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 171 +++++++++++++-------- .../gpu/drm/amd/display/dc/dcn20/dcn20_resource.c | 40 ++--- .../gpu/drm/amd/display/dc/dcn20/dcn20_resource.h | 1 + 3 files changed, 132 insertions(+), 80 deletions(-) (limited to 'drivers/gpu/drm/amd/display') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index cd80d8249d14..a65a1e7820d6 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -532,6 +532,35 @@ static inline void get_vp_scan_direction( *flip_horz_scan_dir = !*flip_horz_scan_dir; } +static void calculate_split_count_and_index(struct pipe_ctx *pipe_ctx, int *split_count, int *split_idx) +{ + *split_count = get_num_odm_splits(pipe_ctx); + *split_idx = 0; + if (*split_count == 0) { + /*Check for mpc split*/ + struct pipe_ctx *split_pipe = pipe_ctx->top_pipe; + + while (split_pipe && split_pipe->plane_state == pipe_ctx->plane_state) { + (*split_idx)++; + (*split_count)++; + split_pipe = split_pipe->top_pipe; + } + split_pipe = pipe_ctx->bottom_pipe; + while (split_pipe && split_pipe->plane_state == pipe_ctx->plane_state) { + (*split_count)++; + split_pipe = split_pipe->bottom_pipe; + } + } else { + /*Get odm split index*/ + struct pipe_ctx *split_pipe = pipe_ctx->prev_odm_pipe; + + while (split_pipe) { + (*split_idx)++; + split_pipe = split_pipe->prev_odm_pipe; + } + } +} + static void calculate_viewport(struct pipe_ctx *pipe_ctx) { const struct dc_plane_state *plane_state = pipe_ctx->plane_state; @@ -541,16 +570,16 @@ static void calculate_viewport(struct pipe_ctx *pipe_ctx) struct rect clip, dest; int vpc_div = (data->format == PIXEL_FORMAT_420BPP8 || data->format == PIXEL_FORMAT_420BPP10) ? 2 : 1; - bool pri_split = pipe_ctx->bottom_pipe && - pipe_ctx->bottom_pipe->plane_state == pipe_ctx->plane_state; - bool sec_split = pipe_ctx->top_pipe && - pipe_ctx->top_pipe->plane_state == pipe_ctx->plane_state; + int split_count = 0; + int split_idx = 0; bool orthogonal_rotation, flip_y_start, flip_x_start; + calculate_split_count_and_index(pipe_ctx, &split_count, &split_idx); + if (stream->view_format == VIEW_3D_FORMAT_SIDE_BY_SIDE || stream->view_format == VIEW_3D_FORMAT_TOP_AND_BOTTOM) { - pri_split = false; - sec_split = false; + split_count = 0; + split_idx = 0; } /* The actual clip is an intersection between stream @@ -609,23 +638,32 @@ static void calculate_viewport(struct pipe_ctx *pipe_ctx) data->viewport.height = clip.height * surf_src.height / dest.height; /* Handle split */ - if (pri_split || sec_split) { + if (split_count) { + /* extra pixels in the division remainder need to go to pipes after + * the extra pixel index minus one(epimo) defined here as: + */ + int epimo = 0; + if (orthogonal_rotation) { - if (flip_y_start != pri_split) - data->viewport.height /= 2; - else { - data->viewport.y += data->viewport.height / 2; - /* Ceil offset pipe */ - data->viewport.height = (data->viewport.height + 1) / 2; - } + if (flip_y_start) + split_idx = split_count - split_idx; + + epimo = split_count - data->viewport.height % (split_count + 1); + + data->viewport.y += (data->viewport.height / (split_count + 1)) * split_idx; + if (split_idx > epimo) + data->viewport.y += split_idx - epimo - 1; + data->viewport.height = data->viewport.height / (split_count + 1) + (split_idx > epimo ? 1 : 0); } else { - if (flip_x_start != pri_split) - data->viewport.width /= 2; - else { - data->viewport.x += data->viewport.width / 2; - /* Ceil offset pipe */ - data->viewport.width = (data->viewport.width + 1) / 2; - } + if (flip_x_start) + split_idx = split_count - split_idx; + + epimo = split_count - data->viewport.width % (split_count + 1); + + data->viewport.x += (data->viewport.width / (split_count + 1)) * split_idx; + if (split_idx > epimo) + data->viewport.x += split_idx - epimo - 1; + data->viewport.width = data->viewport.width / (split_count + 1) + (split_idx > epimo ? 1 : 0); } } @@ -644,58 +682,58 @@ static void calculate_recout(struct pipe_ctx *pipe_ctx) { const struct dc_plane_state *plane_state = pipe_ctx->plane_state; const struct dc_stream_state *stream = pipe_ctx->stream; + struct scaler_data *data = &pipe_ctx->plane_res.scl_data; struct rect surf_clip = plane_state->clip_rect; - bool pri_split = pipe_ctx->bottom_pipe && - pipe_ctx->bottom_pipe->plane_state == pipe_ctx->plane_state; - bool sec_split = pipe_ctx->top_pipe && - pipe_ctx->top_pipe->plane_state == pipe_ctx->plane_state; - bool top_bottom_split = stream->view_format == VIEW_3D_FORMAT_TOP_AND_BOTTOM; - - pipe_ctx->plane_res.scl_data.recout.x = stream->dst.x; + bool pri_split_tb = pipe_ctx->bottom_pipe && + pipe_ctx->bottom_pipe->plane_state == pipe_ctx->plane_state && + stream->view_format == VIEW_3D_FORMAT_TOP_AND_BOTTOM; + bool sec_split_tb = pipe_ctx->top_pipe && + pipe_ctx->top_pipe->plane_state == pipe_ctx->plane_state && + stream->view_format == VIEW_3D_FORMAT_TOP_AND_BOTTOM; + int split_count = 0; + int split_idx = 0; + + calculate_split_count_and_index(pipe_ctx, &split_count, &split_idx); + + data->recout.x = stream->dst.x; if (stream->src.x < surf_clip.x) - pipe_ctx->plane_res.scl_data.recout.x += (surf_clip.x - - stream->src.x) * stream->dst.width + data->recout.x += (surf_clip.x - stream->src.x) * stream->dst.width / stream->src.width; - pipe_ctx->plane_res.scl_data.recout.width = surf_clip.width * - stream->dst.width / stream->src.width; - if (pipe_ctx->plane_res.scl_data.recout.width + pipe_ctx->plane_res.scl_data.recout.x > - stream->dst.x + stream->dst.width) - pipe_ctx->plane_res.scl_data.recout.width = - stream->dst.x + stream->dst.width - - pipe_ctx->plane_res.scl_data.recout.x; + data->recout.width = surf_clip.width * stream->dst.width / stream->src.width; + if (data->recout.width + data->recout.x > stream->dst.x + stream->dst.width) + data->recout.width = stream->dst.x + stream->dst.width - data->recout.x; - pipe_ctx->plane_res.scl_data.recout.y = stream->dst.y; + data->recout.y = stream->dst.y; if (stream->src.y < surf_clip.y) - pipe_ctx->plane_res.scl_data.recout.y += (surf_clip.y - - stream->src.y) * stream->dst.height + data->recout.y += (surf_clip.y - stream->src.y) * stream->dst.height / stream->src.height; - pipe_ctx->plane_res.scl_data.recout.height = surf_clip.height * - stream->dst.height / stream->src.height; - if (pipe_ctx->plane_res.scl_data.recout.height + pipe_ctx->plane_res.scl_data.recout.y > - stream->dst.y + stream->dst.height) - pipe_ctx->plane_res.scl_data.recout.height = - stream->dst.y + stream->dst.height - - pipe_ctx->plane_res.scl_data.recout.y; + data->recout.height = surf_clip.height * stream->dst.height / stream->src.height; + if (data->recout.height + data->recout.y > stream->dst.y + stream->dst.height) + data->recout.height = stream->dst.y + stream->dst.height - data->recout.y; /* Handle h & v split, handle rotation using viewport */ - if (sec_split && top_bottom_split) { - pipe_ctx->plane_res.scl_data.recout.y += - pipe_ctx->plane_res.scl_data.recout.height / 2; + if (sec_split_tb) { + data->recout.y += data->recout.height / 2; /* Floor primary pipe, ceil 2ndary pipe */ - pipe_ctx->plane_res.scl_data.recout.height = - (pipe_ctx->plane_res.scl_data.recout.height + 1) / 2; - } else if (pri_split && top_bottom_split) - pipe_ctx->plane_res.scl_data.recout.height /= 2; - else if (sec_split) { - pipe_ctx->plane_res.scl_data.recout.x += - pipe_ctx->plane_res.scl_data.recout.width / 2; - /* Ceil offset pipe */ - pipe_ctx->plane_res.scl_data.recout.width = - (pipe_ctx->plane_res.scl_data.recout.width + 1) / 2; - } else if (pri_split) - pipe_ctx->plane_res.scl_data.recout.width /= 2; + data->recout.height = (data->recout.height + 1) / 2; + } else if (pri_split_tb) + data->recout.height /= 2; + else if (split_count) { + /* extra pixels in the division remainder need to go to pipes after + * the extra pixel index minus one(epimo) defined here as: + */ + int epimo = split_count - data->recout.width % (split_count + 1); + + /*no recout offset due to odm */ + if (!pipe_ctx->next_odm_pipe && !pipe_ctx->prev_odm_pipe) { + data->recout.x += (data->recout.width / (split_count + 1)) * split_idx; + if (split_idx > epimo) + data->recout.x += split_idx - epimo - 1; + } + data->recout.width = data->recout.width / (split_count + 1) + (split_idx > epimo ? 1 : 0); + } } static void calculate_scaling_ratios(struct pipe_ctx *pipe_ctx) @@ -832,6 +870,7 @@ static void calculate_inits_and_adj_vp(struct pipe_ctx *pipe_ctx) { const struct dc_plane_state *plane_state = pipe_ctx->plane_state; const struct dc_stream_state *stream = pipe_ctx->stream; + struct pipe_ctx *odm_pipe = pipe_ctx->prev_odm_pipe; struct scaler_data *data = &pipe_ctx->plane_res.scl_data; struct rect src = pipe_ctx->plane_state->src_rect; int recout_skip_h, recout_skip_v, surf_size_h, surf_size_v; @@ -869,6 +908,12 @@ static void calculate_inits_and_adj_vp(struct pipe_ctx *pipe_ctx) * stream->dst.width / stream->src.width - src.x * plane_state->dst_rect.width / src.width * stream->dst.width / stream->src.width); + /*modified recout_skip_h calculation due to odm having no recout offset caused by split*/ + while (odm_pipe) { + recout_skip_h += odm_pipe->plane_res.scl_data.recout.width + odm_pipe->plane_res.scl_data.recout.x; + odm_pipe = odm_pipe->prev_odm_pipe; + } + recout_skip_v = data->recout.y - (stream->dst.y + (plane_state->dst_rect.y - stream->src.y) * stream->dst.height / stream->src.height - src.y * plane_state->dst_rect.height / src.height @@ -1021,6 +1066,8 @@ bool resource_build_scaling_params(struct pipe_ctx *pipe_ctx) store_h_border_left + timing->h_border_right; pipe_ctx->plane_res.scl_data.v_active = timing->v_addressable + timing->v_border_top + timing->v_border_bottom; + if (pipe_ctx->next_odm_pipe || pipe_ctx->prev_odm_pipe) + pipe_ctx->plane_res.scl_data.h_active /= get_num_odm_splits(pipe_ctx) + 1; /* Taps calculations */ if (pipe_ctx->plane_res.xfm != NULL) diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c index 85f90f3e24cb..39026df56fa6 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c @@ -1861,20 +1861,20 @@ void dcn20_populate_dml_writeback_from_context( } -static int get_num_odm_heads(struct pipe_ctx *pipe) +int get_num_odm_splits(struct pipe_ctx *pipe) { - int odm_head_count = 0; + int odm_split_count = 0; struct pipe_ctx *next_pipe = pipe->next_odm_pipe; while (next_pipe) { - odm_head_count++; + odm_split_count++; next_pipe = next_pipe->next_odm_pipe; } pipe = pipe->prev_odm_pipe; while (pipe) { - odm_head_count++; + odm_split_count++; pipe = pipe->prev_odm_pipe; } - return odm_head_count ? odm_head_count + 1 : 0; + return odm_split_count; } int dcn20_populate_dml_pipes_from_context( @@ -1956,8 +1956,8 @@ int dcn20_populate_dml_pipes_from_context( pipes[pipe_cnt].dout.dp_lanes = 4; pipes[pipe_cnt].pipe.dest.vtotal_min = res_ctx->pipe_ctx[i].stream->adjust.v_total_min; pipes[pipe_cnt].pipe.dest.vtotal_max = res_ctx->pipe_ctx[i].stream->adjust.v_total_max; - switch (get_num_odm_heads(&res_ctx->pipe_ctx[i])) { - case 2: + switch (get_num_odm_splits(&res_ctx->pipe_ctx[i])) { + case 1: pipes[pipe_cnt].pipe.dest.odm_combine = dm_odm_combine_mode_2to1; break; default: @@ -2124,18 +2124,22 @@ int dcn20_populate_dml_pipes_from_context( pipes[pipe_cnt].pipe.src.dcc = pln->dcc.enable; pipes[pipe_cnt].pipe.dest.recout_width = scl->recout.width; pipes[pipe_cnt].pipe.dest.recout_height = scl->recout.height; - pipes[pipe_cnt].pipe.dest.full_recout_width = scl->recout.width; pipes[pipe_cnt].pipe.dest.full_recout_height = scl->recout.height; - if (res_ctx->pipe_ctx[i].bottom_pipe && res_ctx->pipe_ctx[i].bottom_pipe->plane_state == pln) { - pipes[pipe_cnt].pipe.dest.full_recout_width += - res_ctx->pipe_ctx[i].bottom_pipe->plane_res.scl_data.recout.width; - pipes[pipe_cnt].pipe.dest.full_recout_height += - res_ctx->pipe_ctx[i].bottom_pipe->plane_res.scl_data.recout.height; - } else if (res_ctx->pipe_ctx[i].top_pipe && res_ctx->pipe_ctx[i].top_pipe->plane_state == pln) { - pipes[pipe_cnt].pipe.dest.full_recout_width += - res_ctx->pipe_ctx[i].top_pipe->plane_res.scl_data.recout.width; - pipes[pipe_cnt].pipe.dest.full_recout_height += - res_ctx->pipe_ctx[i].top_pipe->plane_res.scl_data.recout.height; + pipes[pipe_cnt].pipe.dest.full_recout_width = scl->recout.width; + if (pipes[pipe_cnt].pipe.dest.odm_combine == dm_odm_combine_mode_2to1) + pipes[pipe_cnt].pipe.dest.full_recout_width *= 2; + else { + struct pipe_ctx *split_pipe = res_ctx->pipe_ctx[i].bottom_pipe; + + while (split_pipe && split_pipe->plane_state == pln) { + pipes[pipe_cnt].pipe.dest.full_recout_width += split_pipe->plane_res.scl_data.recout.width; + split_pipe = split_pipe->bottom_pipe; + } + split_pipe = res_ctx->pipe_ctx[i].top_pipe; + while (split_pipe && split_pipe->plane_state == pln) { + pipes[pipe_cnt].pipe.dest.full_recout_width += split_pipe->plane_res.scl_data.recout.width; + split_pipe = split_pipe->top_pipe; + } } pipes[pipe_cnt].pipe.scale_ratio_depth.lb_depth = dm_lb_16; diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.h b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.h index f5893840b79b..5180088ab6bc 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.h +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.h @@ -49,6 +49,7 @@ unsigned int dcn20_calc_max_scaled_time( unsigned int time_per_pixel, enum mmhubbub_wbif_mode mode, unsigned int urgent_watermark); +int get_num_odm_splits(struct pipe_ctx *pipe); int dcn20_populate_dml_pipes_from_context( struct dc *dc, struct dc_state *context, display_e2e_pipe_params_st *pipes); struct pipe_ctx *dcn20_acquire_idle_pipe_for_layer( -- cgit From a760fc1bff03f24485324b9ee0c95a45a8cbc5c8 Mon Sep 17 00:00:00 2001 From: Martin Leung Date: Thu, 30 Jan 2020 18:54:44 -0500 Subject: drm/amd/display: add monitor patch to disable SCDC read/write [why] customer issue: found that for their specific panel, EDID register space being overwritten during SCDC read write [how] customer accepted HDMI 2 features not working - disabled SCDC read/write as well as HDMI 2 in general based on monitor patch Signed-off-by: Martin Leung Reviewed-by: Chris Park Acked-by: Rodrigo Siqueira Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 4 ++++ drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c | 8 ++++++++ drivers/gpu/drm/amd/display/dc/dc_types.h | 1 + drivers/gpu/drm/amd/display/dc/dcn10/dcn10_link_encoder.c | 5 +++++ 4 files changed, 18 insertions(+) (limited to 'drivers/gpu/drm/amd/display') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index bed57051f04d..66d8d56f6abd 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -977,6 +977,10 @@ static bool dc_link_detect_helper(struct dc_link *link, if ((prev_sink != NULL) && ((edid_status == EDID_THE_SAME) || (edid_status == EDID_OK))) same_edid = is_same_edid(&prev_sink->dc_edid, &sink->dc_edid); + if (&sink->edid_caps.panel_patch.skip_scdc_overwrite) + link->ctx->dc->debug.hdmi20_disable = true; + + if (link->connector_signal == SIGNAL_TYPE_DISPLAY_PORT && sink_caps.transaction_type == DDC_TRANSACTION_TYPE_I2C_OVER_AUX) { /* diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c index a49c10d5df26..a5586f68b4da 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c @@ -686,6 +686,10 @@ void dal_ddc_service_write_scdc_data(struct ddc_service *ddc_service, uint8_t write_buffer[2] = {0}; /*Lower than 340 Scramble bit from SCDC caps*/ + if (ddc_service->link->local_sink && + ddc_service->link->local_sink->edid_caps.panel_patch.skip_scdc_overwrite) + return; + dal_ddc_service_query_ddc_data(ddc_service, slave_address, &offset, sizeof(offset), &sink_version, sizeof(sink_version)); if (sink_version == 1) { @@ -715,6 +719,10 @@ void dal_ddc_service_read_scdc_data(struct ddc_service *ddc_service) uint8_t offset = HDMI_SCDC_TMDS_CONFIG; uint8_t tmds_config = 0; + if (ddc_service->link->local_sink && + ddc_service->link->local_sink->edid_caps.panel_patch.skip_scdc_overwrite) + return; + dal_ddc_service_query_ddc_data(ddc_service, slave_address, &offset, sizeof(offset), &tmds_config, sizeof(tmds_config)); if (tmds_config & 0x1) { diff --git a/drivers/gpu/drm/amd/display/dc/dc_types.h b/drivers/gpu/drm/amd/display/dc/dc_types.h index 122c96455792..1490732a4b44 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_types.h @@ -229,6 +229,7 @@ struct dc_panel_patch { unsigned int extra_t12_ms; unsigned int extra_delay_backlight_off; unsigned int extra_t7_ms; + unsigned int skip_scdc_overwrite; }; struct dc_edid_caps { diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_link_encoder.c index 1a37c90e9d43..d3617d6785a7 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_link_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_link_encoder.c @@ -782,6 +782,11 @@ bool dcn10_link_encoder_validate_output_with_stream( struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); bool is_valid; + //if SCDC (340-600MHz) is disabled, set to HDMI 1.4 timing limit + if (stream->sink->edid_caps.panel_patch.skip_scdc_overwrite && + enc10->base.features.max_hdmi_pixel_clock > 300000) + enc10->base.features.max_hdmi_pixel_clock = 300000; + switch (stream->signal) { case SIGNAL_TYPE_DVI_SINGLE_LINK: case SIGNAL_TYPE_DVI_DUAL_LINK: -- cgit From 71bbb1fcb1920347b87a7b24efe754769fc5924c Mon Sep 17 00:00:00 2001 From: Nicholas Kazlauskas Date: Mon, 20 Jan 2020 14:56:31 -0500 Subject: drm/amd/display: Don't map ATOM_ENABLE to ATOM_INIT [Why] In DCN hardware sequencer we do actually call ATOM_INIT correctly per pipe. The workaround is not necessary for command table offloading. [How] Drop the workaround since it's not needed. Signed-off-by: Nicholas Kazlauskas Reviewed-by: Chris Park Acked-by: Rodrigo Siqueira Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/bios/command_table2.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'drivers/gpu/drm/amd/display') diff --git a/drivers/gpu/drm/amd/display/dc/bios/command_table2.c b/drivers/gpu/drm/amd/display/dc/bios/command_table2.c index c38f75a56129..8edc2506d49e 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/command_table2.c +++ b/drivers/gpu/drm/amd/display/dc/bios/command_table2.c @@ -711,10 +711,6 @@ static void enable_disp_power_gating_dmcub( power_gating.header.sub_type = DMUB_CMD__VBIOS_ENABLE_DISP_POWER_GATING; power_gating.power_gating.pwr = *pwr; - /* ATOM_ENABLE is old API in DMUB */ - if (power_gating.power_gating.pwr.enable == ATOM_ENABLE) - power_gating.power_gating.pwr.enable = ATOM_INIT; - dc_dmub_srv_cmd_queue(dmcub, &power_gating.header); dc_dmub_srv_cmd_execute(dmcub); dc_dmub_srv_wait_idle(dmcub); -- cgit From 115c7e7f0501716c05d2df5b1b9e06df9241a48c Mon Sep 17 00:00:00 2001 From: Wyatt Wood Date: Mon, 20 Jan 2020 15:52:44 -0500 Subject: drm/amd/display: Add psr get_state call [Why] Driver needs to know PSR state. [How] Use GPINT to call to firmware and get psr state. Signed-off-by: Wyatt Wood Reviewed-by: Nicholas Kazlauskas Acked-by: Rodrigo Siqueira Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 2 +- drivers/gpu/drm/amd/display/dc/dce/dmub_psr.c | 13 ++++++++----- drivers/gpu/drm/amd/display/dc/dce/dmub_psr.h | 2 +- 3 files changed, 10 insertions(+), 7 deletions(-) (limited to 'drivers/gpu/drm/amd/display') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index 66d8d56f6abd..24d99849be5e 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -2451,7 +2451,7 @@ bool dc_link_get_psr_state(const struct dc_link *link, uint32_t *psr_state) struct dmub_psr *psr = dc->res_pool->psr; if (psr != NULL && link->psr_feature_enabled) - psr->funcs->psr_get_state(psr_state); + psr->funcs->psr_get_state(psr, psr_state); else if (dmcu != NULL && link->psr_feature_enabled) dmcu->funcs->get_psr_state(dmcu, psr_state); diff --git a/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.c b/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.c index cacb46979f31..22cd68f7dca0 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.c @@ -29,17 +29,20 @@ #include "../../dmub/inc/dmub_srv.h" #include "dmub_fw_state.h" #include "core_types.h" -#include "ipp.h" #define MAX_PIPES 6 /** * Get PSR state from firmware. */ -static void dmub_psr_get_state(uint32_t *psr_state) +static void dmub_psr_get_state(struct dmub_psr *dmub, uint32_t *psr_state) { - // Not yet implemented - // Trigger GPINT interrupt from firmware + struct dmub_srv *srv = dmub->ctx->dmub_srv->dmub; + + // Send gpint command and wait for ack + dmub_srv_send_gpint_command(srv, DMUB_GPINT__GET_PSR_STATE, 0, 30); + + dmub_srv_get_gpint_response(srv, psr_state); } /** @@ -100,7 +103,7 @@ static void dmub_psr_set_level(struct dmub_psr *dmub, uint16_t psr_level) uint32_t psr_state = 0; struct dc_context *dc = dmub->ctx; - dmub_psr_get_state(&psr_state); + dmub_psr_get_state(dmub, &psr_state); if (psr_state == 0) return; diff --git a/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.h b/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.h index 5e8553d450c9..3de7b9439f42 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.h @@ -36,7 +36,7 @@ struct dmub_psr { struct dmub_psr_funcs { bool (*psr_copy_settings)(struct dmub_psr *dmub, struct dc_link *link, struct psr_context *psr_context); void (*psr_enable)(struct dmub_psr *dmub, bool enable); - void (*psr_get_state)(uint32_t *psr_state); + void (*psr_get_state)(struct dmub_psr *dmub, uint32_t *psr_state); void (*psr_set_level)(struct dmub_psr *dmub, uint16_t psr_level); }; -- cgit From 9a14e81649382c7eb80e7165222c31751225cd81 Mon Sep 17 00:00:00 2001 From: Nicholas Kazlauskas Date: Mon, 3 Feb 2020 09:18:45 -0500 Subject: drm/amd/display: Use fb_base/fb_offset if available for translation [Why] In the case where we do have these passed in then we should be using these instead of the registers - those are only programmed when booting the adapter as primary. [How] Check if fb_base/fb_offset are non-zero. The value of 0 is invalid for fb_base but is valid for fb_offset on dGPU. Signed-off-by: Nicholas Kazlauskas Reviewed-by: Aric Cyr Reviewed-by: Yongqiang Sun Acked-by: Rodrigo Siqueira Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dmub/src/dmub_dcn20.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers/gpu/drm/amd/display') diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn20.c b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn20.c index 479f17bb3800..993e47e99fbe 100644 --- a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn20.c +++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn20.c @@ -60,6 +60,12 @@ static void dmub_dcn20_get_fb_base_offset(struct dmub_srv *dmub, { uint32_t tmp; + if (dmub->fb_base || dmub->fb_offset) { + *fb_base = dmub->fb_base; + *fb_offset = dmub->fb_offset; + return; + } + REG_GET(DCN_VM_FB_LOCATION_BASE, FB_BASE, &tmp); *fb_base = (uint64_t)tmp << 24; -- cgit From 1b53e733238c0f7faa4744ec7c8c6f193649f168 Mon Sep 17 00:00:00 2001 From: Sung Lee Date: Tue, 4 Feb 2020 15:49:54 -0500 Subject: drm/amd/display: DCN2.x Do not program DPPCLK if same value [WHY] Programming DPPCLK to the same value currently set may cause underflow while playing video in certain conditions. [HOW] Only program DPPCLK if clock is not the same as the previous value programmed. Signed-off-by: Sung Lee Reviewed-by: Yongqiang Sun Acked-by: Rodrigo Siqueira Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/clk_mgr/dcn20/dcn20_clk_mgr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu/drm/amd/display') diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn20/dcn20_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn20/dcn20_clk_mgr.c index 495f01e9f2ca..49ce46b543ea 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn20/dcn20_clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn20/dcn20_clk_mgr.c @@ -117,7 +117,7 @@ void dcn20_update_clocks_update_dpp_dto(struct clk_mgr_internal *clk_mgr, prev_dppclk_khz = clk_mgr->base.ctx->dc->current_state->res_ctx.pipe_ctx[i].plane_res.bw.dppclk_khz; - if (safe_to_lower || prev_dppclk_khz < dppclk_khz) { + if ((prev_dppclk_khz > dppclk_khz && safe_to_lower) || prev_dppclk_khz < dppclk_khz) { clk_mgr->dccg->funcs->update_dpp_dto( clk_mgr->dccg, dpp_inst, dppclk_khz); } -- cgit From db70e2c13983926d8d657db3e740264b75ad20a4 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Mon, 10 Feb 2020 23:08:26 +0800 Subject: drm/amd/display: Remove set but not unused variable 'stream_status' drivers/gpu/drm/amd/amdgpu/../display/dc/dcn10/dcn10_hw_sequencer.c: In function dcn10_post_unlock_program_front_end: drivers/gpu/drm/amd/amdgpu/../display/dc/dcn10/dcn10_hw_sequencer.c:2623:29: warning: variable stream_status set but not used [-Wunused-but-set-variable] commit bbf5f6c3f83b ("drm/amd/display: Split program front end part that occur outside lock") involved this unused variable. Signed-off-by: YueHaibing Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) (limited to 'drivers/gpu/drm/amd/display') diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 87e30f60cee6..5f56cc13d6dc 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -2614,7 +2614,7 @@ void dcn10_post_unlock_program_front_end( struct dc *dc, struct dc_state *context) { - int i, j; + int i; DC_LOGGER_INIT(dc->ctx->logger); @@ -2624,14 +2624,8 @@ void dcn10_post_unlock_program_front_end( if (!pipe_ctx->top_pipe && !pipe_ctx->prev_odm_pipe && pipe_ctx->stream) { - struct dc_stream_status *stream_status = NULL; struct timing_generator *tg = pipe_ctx->stream_res.tg; - for (j = 0; j < context->stream_count; j++) { - if (pipe_ctx->stream == context->streams[j]) - stream_status = &context->stream_status[j]; - } - if (context->stream_status[i].plane_count == 0) false_optc_underflow_wa(dc, pipe_ctx->stream, tg); } -- cgit From c17f7220f5a646e5808632b9857387c1b7261f93 Mon Sep 17 00:00:00 2001 From: Bhawanpreet Lakha Date: Tue, 3 Dec 2019 15:52:08 -0500 Subject: drm/amd/display: Handle revoked receivers [Why] PSP added a new return code for revoked receivers (SRM). We need to handle that so we don't retry hdcp This is already being handled on windows [How] Add the enums to psp interface header and handle them. Signed-off-by: Bhawanpreet Lakha Reviewed-by: Nicholas Kazlauskas Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/modules/hdcp/hdcp_psp.c | 28 ++++++++++++++++++---- .../gpu/drm/amd/display/modules/hdcp/hdcp_psp.h | 6 +++-- 2 files changed, 28 insertions(+), 6 deletions(-) (limited to 'drivers/gpu/drm/amd/display') diff --git a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_psp.c b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_psp.c index 7911dc157d5a..844454e0a5ba 100644 --- a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_psp.c +++ b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_psp.c @@ -210,6 +210,10 @@ enum mod_hdcp_status mod_hdcp_hdcp1_validate_rx(struct mod_hdcp *hdcp) } else if (hdcp_cmd->out_msg.hdcp1_first_part_authentication.authentication_status == TA_HDCP_AUTHENTICATION_STATUS__HDCP1_AUTHENTICATED) { hdcp->connection.is_repeater = 0; + } else if (hdcp_cmd->out_msg.hdcp1_first_part_authentication.authentication_status == + TA_HDCP_AUTHENTICATION_STATUS__HDCP1_KSV_REVOKED) { + hdcp->connection.is_hdcp1_revoked = 1; + return MOD_HDCP_STATUS_HDCP1_BKSV_REVOKED; } else return MOD_HDCP_STATUS_HDCP1_VALIDATE_RX_FAILURE; @@ -245,6 +249,7 @@ enum mod_hdcp_status mod_hdcp_hdcp1_validate_ksvlist_vp(struct mod_hdcp *hdcp) { struct psp_context *psp = hdcp->config.psp.handle; struct ta_hdcp_shared_memory *hdcp_cmd; + enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS; hdcp_cmd = (struct ta_hdcp_shared_memory *)psp->hdcp_context.hdcp_shared_buf; memset(hdcp_cmd, 0, sizeof(struct ta_hdcp_shared_memory)); @@ -264,10 +269,19 @@ enum mod_hdcp_status mod_hdcp_hdcp1_validate_ksvlist_vp(struct mod_hdcp *hdcp) psp_hdcp_invoke(psp, hdcp_cmd->cmd_id); - if (hdcp_cmd->hdcp_status != TA_HDCP_STATUS__SUCCESS) - return MOD_HDCP_STATUS_HDCP1_VALIDATE_KSV_LIST_FAILURE; + if (hdcp_cmd->hdcp_status == TA_HDCP_STATUS__SUCCESS && + hdcp_cmd->out_msg.hdcp1_second_part_authentication.authentication_status == + TA_HDCP_AUTHENTICATION_STATUS__HDCP1_AUTHENTICATED) { + status = MOD_HDCP_STATUS_SUCCESS; + } else if (hdcp_cmd->out_msg.hdcp1_second_part_authentication.authentication_status == + TA_HDCP_AUTHENTICATION_STATUS__HDCP1_KSV_REVOKED) { + hdcp->connection.is_hdcp1_revoked = 1; + status = MOD_HDCP_STATUS_HDCP1_KSV_LIST_REVOKED; + } else { + status = MOD_HDCP_STATUS_HDCP1_VALIDATE_KSV_LIST_FAILURE; + } - return MOD_HDCP_STATUS_SUCCESS; + return status; } enum mod_hdcp_status mod_hdcp_hdcp1_enable_dp_stream_encryption(struct mod_hdcp *hdcp) @@ -473,9 +487,12 @@ enum mod_hdcp_status mod_hdcp_hdcp2_validate_ake_cert(struct mod_hdcp *hdcp) hdcp->connection.is_km_stored = msg_out->process.is_km_stored ? 1 : 0; hdcp->connection.is_repeater = msg_out->process.is_repeater ? 1 : 0; return MOD_HDCP_STATUS_SUCCESS; + } else if (msg_out->process.msg1_status == TA_HDCP2_MSG_AUTHENTICATION_STATUS__RECEIVERID_REVOKED) { + hdcp->connection.is_hdcp2_revoked = 1; + return MOD_HDCP_STATUS_HDCP2_AKE_CERT_REVOKED; } - return MOD_HDCP_STATUS_FAILURE; + return MOD_HDCP_STATUS_HDCP2_VALIDATE_AKE_CERT_FAILURE; } enum mod_hdcp_status mod_hdcp_hdcp2_validate_h_prime(struct mod_hdcp *hdcp) @@ -695,6 +712,9 @@ enum mod_hdcp_status mod_hdcp_hdcp2_validate_rx_id_list(struct mod_hdcp *hdcp) hdcp->connection.is_km_stored = msg_out->process.is_km_stored ? 1 : 0; hdcp->connection.is_repeater = msg_out->process.is_repeater ? 1 : 0; return MOD_HDCP_STATUS_SUCCESS; + } else if (msg_out->process.msg1_status == TA_HDCP2_MSG_AUTHENTICATION_STATUS__RECEIVERID_REVOKED) { + hdcp->connection.is_hdcp2_revoked = 1; + return MOD_HDCP_STATUS_HDCP2_RX_ID_LIST_REVOKED; } diff --git a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_psp.h b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_psp.h index d5cb3f46606f..1a663dbbf810 100644 --- a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_psp.h +++ b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_psp.h @@ -240,7 +240,8 @@ enum ta_hdcp_authentication_status { TA_HDCP_AUTHENTICATION_STATUS__HDCP22_AUTHENTICATION_PENDING = 0x06, TA_HDCP_AUTHENTICATION_STATUS__HDCP22_AUTHENTICATION_FAILED = 0x07, TA_HDCP_AUTHENTICATION_STATUS__HDCP22_AUTHENTICATED = 0x08, - TA_HDCP_AUTHENTICATION_STATUS__HDCP1_KSV_VALIDATION_FAILED = 0x09 + TA_HDCP_AUTHENTICATION_STATUS__HDCP1_KSV_VALIDATION_FAILED = 0x09, + TA_HDCP_AUTHENTICATION_STATUS__HDCP1_KSV_REVOKED = 0x0A }; enum ta_hdcp2_msg_authentication_status { @@ -258,7 +259,8 @@ enum ta_hdcp2_msg_authentication_status { TA_HDCP2_MSG_AUTHENTICATION_STATUS__INVALID_SEQ_NUM, TA_HDCP2_MSG_AUTHENTICATION_STATUS__INVALID_SIZE, TA_HDCP2_MSG_AUTHENTICATION_STATUS__INVALID_LENGTH, - TA_HDCP2_MSG_AUTHENTICATION_STATUS__REAUTH_REQUEST + TA_HDCP2_MSG_AUTHENTICATION_STATUS__REAUTH_REQUEST, + TA_HDCP2_MSG_AUTHENTICATION_STATUS__RECEIVERID_REVOKED }; enum ta_hdcp_content_type { -- cgit From 3744ee2c2901656455bbd2af658ab9b673ca5d1d Mon Sep 17 00:00:00 2001 From: Wenjing Liu Date: Thu, 17 Oct 2019 11:13:29 -0400 Subject: drm/amd/display: no hdcp retry if bksv or ksv list is revoked [why] According to the specs when bksv or ksv list fails SRM check, HDCP TX should abort hdcp immediately. However with the current code HDCP will be reattampt upto 4 times. [how] Add the logic that stop HDCP retry if bksv or ksv list is revoked. Signed-off-by: Wenjing Liu Reviewed-by: Jun Lei Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/modules/hdcp/hdcp.c | 3 ++- drivers/gpu/drm/amd/display/modules/hdcp/hdcp.h | 1 + drivers/gpu/drm/amd/display/modules/hdcp/hdcp1_transition.c | 6 ++++-- drivers/gpu/drm/amd/display/modules/hdcp/hdcp_log.c | 4 ++++ drivers/gpu/drm/amd/display/modules/inc/mod_hdcp.h | 2 ++ 5 files changed, 13 insertions(+), 3 deletions(-) (limited to 'drivers/gpu/drm/amd/display') diff --git a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp.c b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp.c index 8aa528e874c4..a7d24734c7cd 100644 --- a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp.c +++ b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp.c @@ -61,7 +61,8 @@ static uint8_t is_cp_desired_hdcp1(struct mod_hdcp *hdcp) return (hdcp->connection.hdcp1_retry_count < MAX_NUM_OF_ATTEMPTS) && is_auth_needed && - !hdcp->connection.link.adjust.hdcp1.disable; + !hdcp->connection.link.adjust.hdcp1.disable && + !hdcp->connection.is_hdcp1_revoked; } static uint8_t is_cp_desired_hdcp2(struct mod_hdcp *hdcp) diff --git a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp.h b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp.h index af78e4f1be68..4d717ec8f14b 100644 --- a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp.h +++ b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp.h @@ -170,6 +170,7 @@ struct mod_hdcp_connection { struct mod_hdcp_display displays[MAX_NUM_OF_DISPLAYS]; uint8_t is_repeater; uint8_t is_km_stored; + uint8_t is_hdcp1_revoked; uint8_t is_hdcp2_revoked; struct mod_hdcp_trace trace; uint8_t hdcp1_retry_count; diff --git a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp1_transition.c b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp1_transition.c index 76edcbe51f71..d66a9f954ade 100644 --- a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp1_transition.c +++ b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp1_transition.c @@ -210,7 +210,8 @@ enum mod_hdcp_status mod_hdcp_hdcp1_dp_transition(struct mod_hdcp *hdcp, fail_and_restart_in_ms(0, &status, output); break; } else if (input->rx_validation != PASS) { - if (hdcp->state.stay_count < 2) { + if (hdcp->state.stay_count < 2 && + !hdcp->connection.is_hdcp1_revoked) { /* allow 2 additional retries */ callback_in_ms(0, output); increment_stay_counter(hdcp); @@ -290,7 +291,8 @@ enum mod_hdcp_status mod_hdcp_hdcp1_dp_transition(struct mod_hdcp *hdcp, fail_and_restart_in_ms(0, &status, output); break; } else if (input->ksvlist_vp_validation != PASS) { - if (hdcp->state.stay_count < 2) { + if (hdcp->state.stay_count < 2 && + !hdcp->connection.is_hdcp1_revoked) { /* allow 2 additional retries */ callback_in_ms(0, output); increment_stay_counter(hdcp); diff --git a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_log.c b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_log.c index 724ebcee9a19..44956f9ba178 100644 --- a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_log.c +++ b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_log.c @@ -90,10 +90,14 @@ char *mod_hdcp_status_to_str(int32_t status) return "MOD_HDCP_STATUS_HDCP1_R0_PRIME_PENDING"; case MOD_HDCP_STATUS_HDCP1_VALIDATE_RX_FAILURE: return "MOD_HDCP_STATUS_HDCP1_VALIDATE_RX_FAILURE"; + case MOD_HDCP_STATUS_HDCP1_BKSV_REVOKED: + return "MOD_HDCP_STATUS_HDCP1_BKSV_REVOKED"; case MOD_HDCP_STATUS_HDCP1_KSV_LIST_NOT_READY: return "MOD_HDCP_STATUS_HDCP1_KSV_LIST_NOT_READY"; case MOD_HDCP_STATUS_HDCP1_VALIDATE_KSV_LIST_FAILURE: return "MOD_HDCP_STATUS_HDCP1_VALIDATE_KSV_LIST_FAILURE"; + case MOD_HDCP_STATUS_HDCP1_KSV_LIST_REVOKED: + return "MOD_HDCP_STATUS_HDCP1_KSV_LIST_REVOKED"; case MOD_HDCP_STATUS_HDCP1_ENABLE_ENCRYPTION: return "MOD_HDCP_STATUS_HDCP1_ENABLE_ENCRYPTION"; case MOD_HDCP_STATUS_HDCP1_ENABLE_STREAM_ENCRYPTION_FAILURE: diff --git a/drivers/gpu/drm/amd/display/modules/inc/mod_hdcp.h b/drivers/gpu/drm/amd/display/modules/inc/mod_hdcp.h index f2a0e1a064da..891bca555e17 100644 --- a/drivers/gpu/drm/amd/display/modules/inc/mod_hdcp.h +++ b/drivers/gpu/drm/amd/display/modules/inc/mod_hdcp.h @@ -56,8 +56,10 @@ enum mod_hdcp_status { MOD_HDCP_STATUS_HDCP1_NOT_CAPABLE, MOD_HDCP_STATUS_HDCP1_R0_PRIME_PENDING, MOD_HDCP_STATUS_HDCP1_VALIDATE_RX_FAILURE, + MOD_HDCP_STATUS_HDCP1_BKSV_REVOKED, MOD_HDCP_STATUS_HDCP1_KSV_LIST_NOT_READY, MOD_HDCP_STATUS_HDCP1_VALIDATE_KSV_LIST_FAILURE, + MOD_HDCP_STATUS_HDCP1_KSV_LIST_REVOKED, MOD_HDCP_STATUS_HDCP1_ENABLE_ENCRYPTION, MOD_HDCP_STATUS_HDCP1_ENABLE_STREAM_ENCRYPTION_FAILURE, MOD_HDCP_STATUS_HDCP1_MAX_CASCADE_EXCEEDED_FAILURE, -- cgit From 9124ee78e35df9e1487cec05a8bbc400a3dd7bba Mon Sep 17 00:00:00 2001 From: Wenjing Liu Date: Thu, 19 Sep 2019 16:06:44 -0400 Subject: drm/amd/display: update HDCP DTM immediately after hardware programming [why] HDCP DTM needs to be aware of the upto date display topology information in order to validate hardware consistency. [how] update HDCP DTM on update_stream_config call. Signed-off-by: Wenjing Liu Reviewed-by: Jun Lei Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/modules/hdcp/hdcp.c | 46 +++----- drivers/gpu/drm/amd/display/modules/hdcp/hdcp.h | 10 +- .../drm/amd/display/modules/hdcp/hdcp1_execution.c | 4 - .../amd/display/modules/hdcp/hdcp1_transition.c | 6 +- .../drm/amd/display/modules/hdcp/hdcp2_execution.c | 6 +- .../amd/display/modules/hdcp/hdcp2_transition.c | 6 +- .../gpu/drm/amd/display/modules/hdcp/hdcp_log.h | 9 ++ .../gpu/drm/amd/display/modules/hdcp/hdcp_psp.c | 129 ++++++++++++--------- 8 files changed, 106 insertions(+), 110 deletions(-) (limited to 'drivers/gpu/drm/amd/display') diff --git a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp.c b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp.c index a7d24734c7cd..83eaec4c6ad7 100644 --- a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp.c +++ b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp.c @@ -104,8 +104,6 @@ static enum mod_hdcp_status execution(struct mod_hdcp *hdcp, event_ctx->unexpected_event = 1; goto out; } - /* update topology event if hdcp is not desired */ - status = mod_hdcp_add_display_topology(hdcp); } else if (is_in_hdcp1_states(hdcp)) { status = mod_hdcp_hdcp1_execution(hdcp, event_ctx, &input->hdcp1); } else if (is_in_hdcp1_dp_states(hdcp)) { @@ -192,14 +190,7 @@ static enum mod_hdcp_status reset_authentication(struct mod_hdcp *hdcp, mod_hdcp_hdcp1_destroy_session(hdcp); } - if (hdcp->auth.trans_input.hdcp1.add_topology == PASS) { - status = mod_hdcp_remove_display_topology(hdcp); - if (status != MOD_HDCP_STATUS_SUCCESS) { - output->callback_needed = 0; - output->watchdog_timer_needed = 0; - goto out; - } - } + HDCP_TOP_RESET_AUTH_TRACE(hdcp); memset(&hdcp->auth, 0, sizeof(struct mod_hdcp_authentication)); memset(&hdcp->state, 0, sizeof(struct mod_hdcp_state)); @@ -213,25 +204,12 @@ static enum mod_hdcp_status reset_authentication(struct mod_hdcp *hdcp, goto out; } } - if (hdcp->auth.trans_input.hdcp2.add_topology == PASS) { - status = mod_hdcp_remove_display_topology(hdcp); - if (status != MOD_HDCP_STATUS_SUCCESS) { - output->callback_needed = 0; - output->watchdog_timer_needed = 0; - goto out; - } - } + HDCP_TOP_RESET_AUTH_TRACE(hdcp); memset(&hdcp->auth, 0, sizeof(struct mod_hdcp_authentication)); memset(&hdcp->state, 0, sizeof(struct mod_hdcp_state)); set_state_id(hdcp, output, HDCP_INITIALIZED); } else if (is_in_cp_not_desired_state(hdcp)) { - status = mod_hdcp_remove_display_topology(hdcp); - if (status != MOD_HDCP_STATUS_SUCCESS) { - output->callback_needed = 0; - output->watchdog_timer_needed = 0; - goto out; - } HDCP_TOP_RESET_AUTH_TRACE(hdcp); memset(&hdcp->auth, 0, sizeof(struct mod_hdcp_authentication)); memset(&hdcp->state, 0, sizeof(struct mod_hdcp_state)); @@ -338,16 +316,19 @@ enum mod_hdcp_status mod_hdcp_add_display(struct mod_hdcp *hdcp, if (status != MOD_HDCP_STATUS_SUCCESS) goto out; - /* add display to connection */ - hdcp->connection.link = *link; - *display_container = *display; - /* reset retry counters */ reset_retry_counts(hdcp); /* reset error trace */ memset(&hdcp->connection.trace, 0, sizeof(hdcp->connection.trace)); + /* add display to connection */ + hdcp->connection.link = *link; + *display_container = *display; + status = mod_hdcp_add_display_to_topology(hdcp, display->index); + if (status != MOD_HDCP_STATUS_SUCCESS) + goto out; + /* request authentication */ if (current_state(hdcp) != HDCP_INITIALIZED) set_state_id(hdcp, output, HDCP_INITIALIZED); @@ -380,15 +361,18 @@ enum mod_hdcp_status mod_hdcp_remove_display(struct mod_hdcp *hdcp, if (status != MOD_HDCP_STATUS_SUCCESS) goto out; - /* remove display */ - display->state = MOD_HDCP_DISPLAY_INACTIVE; - /* clear retry counters */ reset_retry_counts(hdcp); /* reset error trace */ memset(&hdcp->connection.trace, 0, sizeof(hdcp->connection.trace)); + /* remove display */ + status = mod_hdcp_remove_display_from_topology(hdcp, index); + if (status != MOD_HDCP_STATUS_SUCCESS) + goto out; + display->state = MOD_HDCP_DISPLAY_INACTIVE; + /* request authentication for remaining displays*/ if (get_active_display_count(hdcp) > 0) callback_in_ms(hdcp->connection.link.adjust.auth_delay * 1000, diff --git a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp.h b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp.h index 4d717ec8f14b..b09d2f5502b3 100644 --- a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp.h +++ b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp.h @@ -41,7 +41,6 @@ enum mod_hdcp_trans_input_result { struct mod_hdcp_transition_input_hdcp1 { uint8_t bksv_read; uint8_t bksv_validation; - uint8_t add_topology; uint8_t create_session; uint8_t an_write; uint8_t aksv_write; @@ -71,7 +70,6 @@ struct mod_hdcp_transition_input_hdcp1 { struct mod_hdcp_transition_input_hdcp2 { uint8_t hdcp2version_read; uint8_t hdcp2_capable_check; - uint8_t add_topology; uint8_t create_session; uint8_t ake_init_prepare; uint8_t ake_init_write; @@ -328,10 +326,10 @@ void mod_hdcp_dump_binary_message(uint8_t *msg, uint32_t msg_size, /* TODO: add adjustment log */ /* psp functions */ -enum mod_hdcp_status mod_hdcp_add_display_topology( - struct mod_hdcp *hdcp); -enum mod_hdcp_status mod_hdcp_remove_display_topology( - struct mod_hdcp *hdcp); +enum mod_hdcp_status mod_hdcp_add_display_to_topology( + struct mod_hdcp *hdcp, uint8_t index); +enum mod_hdcp_status mod_hdcp_remove_display_from_topology( + struct mod_hdcp *hdcp, uint8_t index); enum mod_hdcp_status mod_hdcp_hdcp1_create_session(struct mod_hdcp *hdcp); enum mod_hdcp_status mod_hdcp_hdcp1_destroy_session(struct mod_hdcp *hdcp); enum mod_hdcp_status mod_hdcp_hdcp1_validate_rx(struct mod_hdcp *hdcp); diff --git a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp1_execution.c b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp1_execution.c index 37670db64855..37c8c05497d6 100644 --- a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp1_execution.c +++ b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp1_execution.c @@ -168,10 +168,6 @@ static enum mod_hdcp_status exchange_ksvs(struct mod_hdcp *hdcp, goto out; } - if (!mod_hdcp_execute_and_set(mod_hdcp_add_display_topology, - &input->add_topology, &status, - hdcp, "add_topology")) - goto out; if (!mod_hdcp_execute_and_set(mod_hdcp_hdcp1_create_session, &input->create_session, &status, hdcp, "create_session")) diff --git a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp1_transition.c b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp1_transition.c index d66a9f954ade..5bc6706d2af7 100644 --- a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp1_transition.c +++ b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp1_transition.c @@ -46,8 +46,7 @@ enum mod_hdcp_status mod_hdcp_hdcp1_transition(struct mod_hdcp *hdcp, set_state_id(hdcp, output, H1_A1_EXCHANGE_KSVS); break; case H1_A1_EXCHANGE_KSVS: - if (input->add_topology != PASS || - input->create_session != PASS) { + if (input->create_session != PASS) { /* out of sync with psp state */ adjust->hdcp1.disable = 1; fail_and_restart_in_ms(0, &status, output); @@ -173,8 +172,7 @@ enum mod_hdcp_status mod_hdcp_hdcp1_dp_transition(struct mod_hdcp *hdcp, set_state_id(hdcp, output, D1_A1_EXCHANGE_KSVS); break; case D1_A1_EXCHANGE_KSVS: - if (input->add_topology != PASS || - input->create_session != PASS) { + if (input->create_session != PASS) { /* out of sync with psp state */ adjust->hdcp1.disable = 1; fail_and_restart_in_ms(0, &status, output); diff --git a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp2_execution.c b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp2_execution.c index f730b94ac3c0..432b2a016e56 100644 --- a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp2_execution.c +++ b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp2_execution.c @@ -259,6 +259,7 @@ static enum mod_hdcp_status known_hdcp2_capable_rx(struct mod_hdcp *hdcp, event_ctx->unexpected_event = 1; goto out; } + if (!mod_hdcp_execute_and_set(mod_hdcp_read_hdcp2version, &input->hdcp2version_read, &status, hdcp, "hdcp2version_read")) @@ -281,10 +282,7 @@ static enum mod_hdcp_status send_ake_init(struct mod_hdcp *hdcp, event_ctx->unexpected_event = 1; goto out; } - if (!mod_hdcp_execute_and_set(mod_hdcp_add_display_topology, - &input->add_topology, &status, - hdcp, "add_topology")) - goto out; + if (!mod_hdcp_execute_and_set(mod_hdcp_hdcp2_create_session, &input->create_session, &status, hdcp, "create_session")) diff --git a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp2_transition.c b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp2_transition.c index 8cae3e3aacd5..e738c7ae66ec 100644 --- a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp2_transition.c +++ b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp2_transition.c @@ -47,8 +47,7 @@ enum mod_hdcp_status mod_hdcp_hdcp2_transition(struct mod_hdcp *hdcp, } break; case H2_A1_SEND_AKE_INIT: - if (input->add_topology != PASS || - input->create_session != PASS || + if (input->create_session != PASS || input->ake_init_prepare != PASS) { /* out of sync with psp state */ adjust->hdcp2.disable = 1; @@ -389,8 +388,7 @@ enum mod_hdcp_status mod_hdcp_hdcp2_dp_transition(struct mod_hdcp *hdcp, } break; case D2_A1_SEND_AKE_INIT: - if (input->add_topology != PASS || - input->create_session != PASS || + if (input->create_session != PASS || input->ake_init_prepare != PASS) { /* out of sync with psp state */ adjust->hdcp2.disable = 1; diff --git a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_log.h b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_log.h index ff91373ebada..6e844825ad23 100644 --- a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_log.h +++ b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_log.h @@ -49,6 +49,15 @@ HDCP_LOG_VER(hdcp, \ "[Link %d] HDCP 2.2 enabled on display %d", \ hdcp->config.index, displayIndex) +#define HDCP_HDCP1_DISABLED_TRACE(hdcp, displayIndex) \ + HDCP_LOG_VER(hdcp, \ + "[Link %d] HDCP 1.4 disabled on display %d", \ + hdcp->config.index, displayIndex) +#define HDCP_HDCP2_DISABLED_TRACE(hdcp, displayIndex) \ + HDCP_LOG_VER(hdcp, \ + "[Link %d] HDCP 2.2 disabled on display %d", \ + hdcp->config.index, displayIndex) + /* state machine logs */ #define HDCP_REMOVE_DISPLAY_TRACE(hdcp, displayIndex) \ HDCP_LOG_FSM(hdcp, \ diff --git a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_psp.c b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_psp.c index 844454e0a5ba..acbe3e8a8eb7 100644 --- a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_psp.c +++ b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_psp.c @@ -44,85 +44,82 @@ static void hdcp2_message_init(struct mod_hdcp *hdcp, in->process.msg3_desc.msg_id = TA_HDCP_HDCP2_MSG_ID__NULL_MESSAGE; in->process.msg3_desc.msg_size = 0; } -enum mod_hdcp_status mod_hdcp_remove_display_topology(struct mod_hdcp *hdcp) -{ - - struct psp_context *psp = hdcp->config.psp.handle; - struct ta_dtm_shared_memory *dtm_cmd; - struct mod_hdcp_display *display = NULL; - uint8_t i; +enum mod_hdcp_status mod_hdcp_remove_display_from_topology( + struct mod_hdcp *hdcp, uint8_t index) + { + struct psp_context *psp = hdcp->config.psp.handle; + struct ta_dtm_shared_memory *dtm_cmd; + struct mod_hdcp_display *display = + get_active_display_at_index(hdcp, index); dtm_cmd = (struct ta_dtm_shared_memory *)psp->dtm_context.dtm_shared_buf; - for (i = 0; i < MAX_NUM_OF_DISPLAYS; i++) { - if (is_display_added(&(hdcp->connection.displays[i]))) { - - memset(dtm_cmd, 0, sizeof(struct ta_dtm_shared_memory)); - - display = &hdcp->connection.displays[i]; + if (!display || !is_display_added(display)) + return MOD_HDCP_STATUS_DISPLAY_NOT_FOUND; - dtm_cmd->cmd_id = TA_DTM_COMMAND__TOPOLOGY_UPDATE_V2; - dtm_cmd->dtm_in_message.topology_update_v2.display_handle = display->index; - dtm_cmd->dtm_in_message.topology_update_v2.is_active = 0; - dtm_cmd->dtm_status = TA_DTM_STATUS__GENERIC_FAILURE; + memset(dtm_cmd, 0, sizeof(struct ta_dtm_shared_memory)); - psp_dtm_invoke(psp, dtm_cmd->cmd_id); + dtm_cmd->cmd_id = TA_DTM_COMMAND__TOPOLOGY_UPDATE_V2; + dtm_cmd->dtm_in_message.topology_update_v2.display_handle = display->index; + dtm_cmd->dtm_in_message.topology_update_v2.is_active = 0; + dtm_cmd->dtm_status = TA_DTM_STATUS__GENERIC_FAILURE; - if (dtm_cmd->dtm_status != TA_DTM_STATUS__SUCCESS) - return MOD_HDCP_STATUS_UPDATE_TOPOLOGY_FAILURE; + psp_dtm_invoke(psp, dtm_cmd->cmd_id); - display->state = MOD_HDCP_DISPLAY_ACTIVE; - HDCP_TOP_REMOVE_DISPLAY_TRACE(hdcp, display->index); - } - } + if (dtm_cmd->dtm_status != TA_DTM_STATUS__SUCCESS) + return MOD_HDCP_STATUS_UPDATE_TOPOLOGY_FAILURE; - return MOD_HDCP_STATUS_SUCCESS; -} + display->state = MOD_HDCP_DISPLAY_ACTIVE; + HDCP_TOP_REMOVE_DISPLAY_TRACE(hdcp, display->index); + + return MOD_HDCP_STATUS_SUCCESS; + } -enum mod_hdcp_status mod_hdcp_add_display_topology(struct mod_hdcp *hdcp) +enum mod_hdcp_status mod_hdcp_add_display_to_topology( + struct mod_hdcp *hdcp, uint8_t index) { struct psp_context *psp = hdcp->config.psp.handle; struct ta_dtm_shared_memory *dtm_cmd; - struct mod_hdcp_display *display = NULL; + struct mod_hdcp_display *display = + get_active_display_at_index(hdcp, index); struct mod_hdcp_link *link = &hdcp->connection.link; - uint8_t i; if (!psp->dtm_context.dtm_initialized) { DRM_ERROR("Failed to add display topology, DTM TA is not initialized."); return MOD_HDCP_STATUS_FAILURE; } + if (!display || is_display_added(display)) + return MOD_HDCP_STATUS_UPDATE_TOPOLOGY_FAILURE; + dtm_cmd = (struct ta_dtm_shared_memory *)psp->dtm_context.dtm_shared_buf; - for (i = 0; i < MAX_NUM_OF_DISPLAYS; i++) { - if (hdcp->connection.displays[i].state == MOD_HDCP_DISPLAY_ACTIVE) { - display = &hdcp->connection.displays[i]; - - memset(dtm_cmd, 0, sizeof(struct ta_dtm_shared_memory)); - - dtm_cmd->cmd_id = TA_DTM_COMMAND__TOPOLOGY_UPDATE_V2; - dtm_cmd->dtm_in_message.topology_update_v2.display_handle = display->index; - dtm_cmd->dtm_in_message.topology_update_v2.is_active = 1; - dtm_cmd->dtm_in_message.topology_update_v2.controller = display->controller; - dtm_cmd->dtm_in_message.topology_update_v2.ddc_line = link->ddc_line; - dtm_cmd->dtm_in_message.topology_update_v2.dig_be = link->dig_be; - dtm_cmd->dtm_in_message.topology_update_v2.dig_fe = display->dig_fe; - dtm_cmd->dtm_in_message.topology_update_v2.dp_mst_vcid = display->vc_id; - dtm_cmd->dtm_in_message.topology_update_v2.max_hdcp_supported_version = - TA_DTM_HDCP_VERSION_MAX_SUPPORTED__2_2; - dtm_cmd->dtm_status = TA_DTM_STATUS__GENERIC_FAILURE; - - psp_dtm_invoke(psp, dtm_cmd->cmd_id); - - if (dtm_cmd->dtm_status != TA_DTM_STATUS__SUCCESS) - return MOD_HDCP_STATUS_UPDATE_TOPOLOGY_FAILURE; - - display->state = MOD_HDCP_DISPLAY_ACTIVE_AND_ADDED; - HDCP_TOP_ADD_DISPLAY_TRACE(hdcp, display->index); - } - } + memset(dtm_cmd, 0, sizeof(struct ta_dtm_shared_memory)); - return MOD_HDCP_STATUS_SUCCESS; + dtm_cmd->cmd_id = TA_DTM_COMMAND__TOPOLOGY_UPDATE_V2; + dtm_cmd->dtm_in_message.topology_update_v2.display_handle = display->index; + dtm_cmd->dtm_in_message.topology_update_v2.is_active = 1; + dtm_cmd->dtm_in_message.topology_update_v2.controller = display->controller; + dtm_cmd->dtm_in_message.topology_update_v2.ddc_line = link->ddc_line; + dtm_cmd->dtm_in_message.topology_update_v2.dig_be = link->dig_be; + dtm_cmd->dtm_in_message.topology_update_v2.dig_fe = display->dig_fe; + if (is_dp_hdcp(hdcp)) + dtm_cmd->dtm_in_message.topology_update_v2.is_assr = link->dp.assr_supported; + + dtm_cmd->dtm_in_message.topology_update_v2.dp_mst_vcid = display->vc_id; + dtm_cmd->dtm_in_message.topology_update_v2.max_hdcp_supported_version = + TA_DTM_HDCP_VERSION_MAX_SUPPORTED__2_2; + dtm_cmd->dtm_status = TA_DTM_STATUS__GENERIC_FAILURE; + + psp_dtm_invoke(psp, dtm_cmd->cmd_id); + + if (dtm_cmd->dtm_status != TA_DTM_STATUS__SUCCESS) + return MOD_HDCP_STATUS_UPDATE_TOPOLOGY_FAILURE; + + display->state = MOD_HDCP_DISPLAY_ACTIVE_AND_ADDED; + HDCP_TOP_ADD_DISPLAY_TRACE(hdcp, display->index); + + return MOD_HDCP_STATUS_SUCCESS; } enum mod_hdcp_status mod_hdcp_hdcp1_create_session(struct mod_hdcp *hdcp) @@ -164,6 +161,7 @@ enum mod_hdcp_status mod_hdcp_hdcp1_destroy_session(struct mod_hdcp *hdcp) struct psp_context *psp = hdcp->config.psp.handle; struct ta_hdcp_shared_memory *hdcp_cmd; + uint8_t i = 0; hdcp_cmd = (struct ta_hdcp_shared_memory *)psp->hdcp_context.hdcp_shared_buf; memset(hdcp_cmd, 0, sizeof(struct ta_hdcp_shared_memory)); @@ -177,6 +175,14 @@ enum mod_hdcp_status mod_hdcp_hdcp1_destroy_session(struct mod_hdcp *hdcp) return MOD_HDCP_STATUS_HDCP1_DESTROY_SESSION_FAILURE; HDCP_TOP_HDCP1_DESTROY_SESSION_TRACE(hdcp); + for (i = 0; i < MAX_NUM_OF_DISPLAYS; i++) + if (is_display_encryption_enabled( + &hdcp->connection.displays[i])) { + hdcp->connection.displays[i].state = + MOD_HDCP_DISPLAY_ACTIVE_AND_ADDED; + HDCP_HDCP1_DISABLED_TRACE(hdcp, + hdcp->connection.displays[i].index); + } return MOD_HDCP_STATUS_SUCCESS; } @@ -399,6 +405,7 @@ enum mod_hdcp_status mod_hdcp_hdcp2_destroy_session(struct mod_hdcp *hdcp) { struct psp_context *psp = hdcp->config.psp.handle; struct ta_hdcp_shared_memory *hdcp_cmd; + uint8_t i = 0; hdcp_cmd = (struct ta_hdcp_shared_memory *)psp->hdcp_context.hdcp_shared_buf; memset(hdcp_cmd, 0, sizeof(struct ta_hdcp_shared_memory)); @@ -412,6 +419,14 @@ enum mod_hdcp_status mod_hdcp_hdcp2_destroy_session(struct mod_hdcp *hdcp) return MOD_HDCP_STATUS_HDCP2_DESTROY_SESSION_FAILURE; HDCP_TOP_HDCP2_DESTROY_SESSION_TRACE(hdcp); + for (i = 0; i < MAX_NUM_OF_DISPLAYS; i++) + if (is_display_encryption_enabled( + &hdcp->connection.displays[i])) { + hdcp->connection.displays[i].state = + MOD_HDCP_DISPLAY_ACTIVE_AND_ADDED; + HDCP_HDCP2_DISABLED_TRACE(hdcp, + hdcp->connection.displays[i].index); + } return MOD_HDCP_STATUS_SUCCESS; } -- cgit From b215010fd3456bb1b5beb88f199cfd21aa1e7571 Mon Sep 17 00:00:00 2001 From: Bhawanpreet Lakha Date: Thu, 6 Feb 2020 14:26:38 -0500 Subject: drm/amd/display: fix backwards byte order in rx_caps. We were using incorrect byte order after we started using the drm_defines So fix it. Fixes: 02837a91ae75 ("drm/amd/display: add and use defines from drm_hdcp.h") Signed-off-by: JinZe.Xu Signed-off-by: Bhawanpreet Lakha Reviewed-by: Wenjing Liu Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/modules/hdcp/hdcp2_execution.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/gpu/drm/amd/display') diff --git a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp2_execution.c b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp2_execution.c index 432b2a016e56..340df6d406f9 100644 --- a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp2_execution.c +++ b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp2_execution.c @@ -46,8 +46,8 @@ static inline enum mod_hdcp_status check_hdcp2_capable(struct mod_hdcp *hdcp) enum mod_hdcp_status status; if (is_dp_hdcp(hdcp)) - status = (hdcp->auth.msg.hdcp2.rxcaps_dp[2] & HDCP_2_2_RX_CAPS_VERSION_VAL) && - HDCP_2_2_DP_HDCP_CAPABLE(hdcp->auth.msg.hdcp2.rxcaps_dp[0]) ? + status = (hdcp->auth.msg.hdcp2.rxcaps_dp[0] == HDCP_2_2_RX_CAPS_VERSION_VAL) && + HDCP_2_2_DP_HDCP_CAPABLE(hdcp->auth.msg.hdcp2.rxcaps_dp[2]) ? MOD_HDCP_STATUS_SUCCESS : MOD_HDCP_STATUS_HDCP2_NOT_CAPABLE; else -- cgit From 4a9a4e3a7c2aacf4d366d4918349e8d34bd531e3 Mon Sep 17 00:00:00 2001 From: Bhawanpreet Lakha Date: Thu, 6 Feb 2020 15:46:11 -0500 Subject: drm/amd/display: Fix message for encryption -msg_in is not needed for enabling encryption. -Use hdcp2_set_encryption instead of hdcp1_enable_encryption for hdcp2.2 Signed-off-by: Bhawanpreet Lakha Reviewed-by: Nicholas Kazlauskas Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/modules/hdcp/hdcp_psp.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) (limited to 'drivers/gpu/drm/amd/display') diff --git a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_psp.c b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_psp.c index acbe3e8a8eb7..d9cb2383d6de 100644 --- a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_psp.c +++ b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_psp.c @@ -662,20 +662,15 @@ enum mod_hdcp_status mod_hdcp_hdcp2_enable_encryption(struct mod_hdcp *hdcp) { struct psp_context *psp = hdcp->config.psp.handle; struct ta_hdcp_shared_memory *hdcp_cmd; - struct ta_hdcp_cmd_hdcp2_process_prepare_authentication_message_input_v2 *msg_in; struct mod_hdcp_display *display = get_first_added_display(hdcp); hdcp_cmd = (struct ta_hdcp_shared_memory *)psp->hdcp_context.hdcp_shared_buf; memset(hdcp_cmd, 0, sizeof(struct ta_hdcp_shared_memory)); - msg_in = &hdcp_cmd->in_msg.hdcp2_prepare_process_authentication_message_v2; - - hdcp2_message_init(hdcp, msg_in); - if (!display) return MOD_HDCP_STATUS_DISPLAY_NOT_FOUND; - hdcp_cmd->in_msg.hdcp1_enable_encryption.session_handle = hdcp->auth.id; + hdcp_cmd->in_msg.hdcp2_set_encryption.session_handle = hdcp->auth.id; hdcp_cmd->cmd_id = TA_HDCP_COMMAND__HDCP2_SET_ENCRYPTION; psp_hdcp_invoke(psp, hdcp_cmd->cmd_id); -- cgit From 09034ae43f4e4a0c76aaf28f15e879513dc0b161 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 11 Feb 2020 23:21:04 -0500 Subject: drm/amdgpu/display: extend DCN guard in dal_bios_parser_init_cmd_tbl_helper2 To cover DCN 2.x. Reviewed-by: Zhan Liu Tested-by: Rodrigo Siqueira Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/bios/command_table_helper2.c | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) (limited to 'drivers/gpu/drm/amd/display') diff --git a/drivers/gpu/drm/amd/display/dc/bios/command_table_helper2.c b/drivers/gpu/drm/amd/display/dc/bios/command_table_helper2.c index 7388c987c595..204d7942a6e5 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/command_table_helper2.c +++ b/drivers/gpu/drm/amd/display/dc/bios/command_table_helper2.c @@ -53,25 +53,18 @@ bool dal_bios_parser_init_cmd_tbl_helper2( case DCE_VERSION_11_2: case DCE_VERSION_11_22: + case DCE_VERSION_12_0: + case DCE_VERSION_12_1: *h = dal_cmd_tbl_helper_dce112_get_table2(); return true; #if defined(CONFIG_DRM_AMD_DC_DCN) case DCN_VERSION_1_0: case DCN_VERSION_1_01: - *h = dal_cmd_tbl_helper_dce112_get_table2(); - return true; -#endif - case DCN_VERSION_2_0: - *h = dal_cmd_tbl_helper_dce112_get_table2(); - return true; case DCN_VERSION_2_1: *h = dal_cmd_tbl_helper_dce112_get_table2(); return true; - case DCE_VERSION_12_0: - case DCE_VERSION_12_1: - *h = dal_cmd_tbl_helper_dce112_get_table2(); - return true; +#endif default: /* Unsupported DCE */ -- cgit From cf2156e240bcb732536d9de60a9f30b9d92cf965 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 11 Feb 2020 23:22:04 -0500 Subject: drm/amdgpu/display: extend DCN guards to cover dcn2.x related headers. Reviewed-by: Zhan Liu Tested-by: Rodrigo Siqueira Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 4 ++-- drivers/gpu/drm/amd/display/dc/gpio/hw_factory.c | 2 +- drivers/gpu/drm/amd/display/dc/gpio/hw_translate.c | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/gpu/drm/amd/display') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index a65a1e7820d6..c02e5994d32b 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -46,12 +46,12 @@ #include "dce100/dce100_resource.h" #include "dce110/dce110_resource.h" #include "dce112/dce112_resource.h" +#include "dce120/dce120_resource.h" #if defined(CONFIG_DRM_AMD_DC_DCN) #include "dcn10/dcn10_resource.h" -#endif #include "dcn20/dcn20_resource.h" #include "dcn21/dcn21_resource.h" -#include "dce120/dce120_resource.h" +#endif #define DC_LOGGER_INIT(logger) diff --git a/drivers/gpu/drm/amd/display/dc/gpio/hw_factory.c b/drivers/gpu/drm/amd/display/dc/gpio/hw_factory.c index d2d36d48caaa..f252af1947c3 100644 --- a/drivers/gpu/drm/amd/display/dc/gpio/hw_factory.c +++ b/drivers/gpu/drm/amd/display/dc/gpio/hw_factory.c @@ -47,9 +47,9 @@ #include "dce120/hw_factory_dce120.h" #if defined(CONFIG_DRM_AMD_DC_DCN) #include "dcn10/hw_factory_dcn10.h" -#endif #include "dcn20/hw_factory_dcn20.h" #include "dcn21/hw_factory_dcn21.h" +#endif #include "diagnostics/hw_factory_diag.h" diff --git a/drivers/gpu/drm/amd/display/dc/gpio/hw_translate.c b/drivers/gpu/drm/amd/display/dc/gpio/hw_translate.c index 5d396657a1ee..04e2c0f74cb0 100644 --- a/drivers/gpu/drm/amd/display/dc/gpio/hw_translate.c +++ b/drivers/gpu/drm/amd/display/dc/gpio/hw_translate.c @@ -45,9 +45,9 @@ #include "dce120/hw_translate_dce120.h" #if defined(CONFIG_DRM_AMD_DC_DCN) #include "dcn10/hw_translate_dcn10.h" -#endif #include "dcn20/hw_translate_dcn20.h" #include "dcn21/hw_translate_dcn21.h" +#endif #include "diagnostics/hw_translate_diag.h" -- cgit From 228a10d4e1b018ca777281de22276f291bd25a2f Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 11 Feb 2020 23:29:04 -0500 Subject: drm/amdgpu/display move get_num_odm_splits() into dc_resource.c It's used by more than just DCN2.0. Fixes missing symbol when amdgpu is built without DCN support. Reviewed-by: Zhan Liu Tested-by: Rodrigo Siqueira Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 16 ++++++++++++++++ drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c | 16 ---------------- drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.h | 1 - drivers/gpu/drm/amd/display/dc/inc/resource.h | 3 +++ 4 files changed, 19 insertions(+), 17 deletions(-) (limited to 'drivers/gpu/drm/amd/display') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index c02e5994d32b..572ce3842535 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -532,6 +532,22 @@ static inline void get_vp_scan_direction( *flip_horz_scan_dir = !*flip_horz_scan_dir; } +int get_num_odm_splits(struct pipe_ctx *pipe) +{ + int odm_split_count = 0; + struct pipe_ctx *next_pipe = pipe->next_odm_pipe; + while (next_pipe) { + odm_split_count++; + next_pipe = next_pipe->next_odm_pipe; + } + pipe = pipe->prev_odm_pipe; + while (pipe) { + odm_split_count++; + pipe = pipe->prev_odm_pipe; + } + return odm_split_count; +} + static void calculate_split_count_and_index(struct pipe_ctx *pipe_ctx, int *split_count, int *split_idx) { *split_count = get_num_odm_splits(pipe_ctx); diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c index 39026df56fa6..1061faccec9c 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c @@ -1861,22 +1861,6 @@ void dcn20_populate_dml_writeback_from_context( } -int get_num_odm_splits(struct pipe_ctx *pipe) -{ - int odm_split_count = 0; - struct pipe_ctx *next_pipe = pipe->next_odm_pipe; - while (next_pipe) { - odm_split_count++; - next_pipe = next_pipe->next_odm_pipe; - } - pipe = pipe->prev_odm_pipe; - while (pipe) { - odm_split_count++; - pipe = pipe->prev_odm_pipe; - } - return odm_split_count; -} - int dcn20_populate_dml_pipes_from_context( struct dc *dc, struct dc_state *context, display_e2e_pipe_params_st *pipes) { diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.h b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.h index 5180088ab6bc..f5893840b79b 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.h +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.h @@ -49,7 +49,6 @@ unsigned int dcn20_calc_max_scaled_time( unsigned int time_per_pixel, enum mmhubbub_wbif_mode mode, unsigned int urgent_watermark); -int get_num_odm_splits(struct pipe_ctx *pipe); int dcn20_populate_dml_pipes_from_context( struct dc *dc, struct dc_state *context, display_e2e_pipe_params_st *pipes); struct pipe_ctx *dcn20_acquire_idle_pipe_for_layer( diff --git a/drivers/gpu/drm/amd/display/dc/inc/resource.h b/drivers/gpu/drm/amd/display/dc/inc/resource.h index 5ae8ada154ef..ca4c36c0c9bc 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/resource.h +++ b/drivers/gpu/drm/amd/display/dc/inc/resource.h @@ -179,4 +179,7 @@ unsigned int resource_pixel_format_to_bpp(enum surface_pixel_format format); void get_audio_check(struct audio_info *aud_modes, struct audio_check *aud_chk); + +int get_num_odm_splits(struct pipe_ctx *pipe); + #endif /* DRIVERS_GPU_DRM_AMD_DC_DEV_DC_INC_RESOURCE_H_ */ -- cgit From 5fbdb1f38d16a75d35f4111b2f0cf1220ca1ecd3 Mon Sep 17 00:00:00 2001 From: Nathan Chancellor Date: Fri, 14 Feb 2020 13:24:39 -0500 Subject: drm/amd/display: Don't take the address of skip_scdc_overwrite in dc_link_detect_helper Clang warns: ../drivers/gpu/drm/amd/amdgpu/../display/dc/core/dc_link.c:980:36: warning: address of 'sink->edid_caps.panel_patch.skip_scdc_overwrite' will always evaluate to 'true' [-Wpointer-bool-conversion] if (&sink->edid_caps.panel_patch.skip_scdc_overwrite) ~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~ 1 warning generated. This is probably not what was intended so remove the address of operator, which matches how skip_scdc_overwrite is handled in the rest of the driver. While we're here, drop an extra newline after this if block. Fixes: a760fc1bff03 ("drm/amd/display: add monitor patch to disable SCDC read/write") Link: https://github.com/ClangBuiltLinux/linux/issues/879 Signed-off-by: Nathan Chancellor Signed-off-by: Zhan Liu Reviewed-by: Zhan Liu Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/gpu/drm/amd/display') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index 24d99849be5e..a3bfa05c545e 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -977,10 +977,9 @@ static bool dc_link_detect_helper(struct dc_link *link, if ((prev_sink != NULL) && ((edid_status == EDID_THE_SAME) || (edid_status == EDID_OK))) same_edid = is_same_edid(&prev_sink->dc_edid, &sink->dc_edid); - if (&sink->edid_caps.panel_patch.skip_scdc_overwrite) + if (sink->edid_caps.panel_patch.skip_scdc_overwrite) link->ctx->dc->debug.hdmi20_disable = true; - if (link->connector_signal == SIGNAL_TYPE_DISPLAY_PORT && sink_caps.transaction_type == DDC_TRANSACTION_TYPE_I2C_OVER_AUX) { /* -- cgit From f739ce5768eddbe573c8b30d8ac109de67c57d29 Mon Sep 17 00:00:00 2001 From: Zhan Liu Date: Fri, 21 Feb 2020 17:25:47 -0500 Subject: drm/amd/display: Add aconnector condition check for dpcd read [Why] core_link_read_dpcd() will invoke dm_helpers_dp_read_dpcd(), which needs to read dpcd info with the help of aconnector. If aconnector (dc->links[i]->prev) is NULL, then dpcd status cannot be read. As a result, dpcd read fails and a line of error will be printed out in dmesg.log as: "*ERROR* Failed to found connector for link!" [How] Make sure that aconnector (dc->links[i]->prev) is not NULL, then read dpcd status. Signed-off-by: Zhan Liu Reviewed-by: Joseph Gravenor Signed-off-by: Alex Deucher --- .../drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) (limited to 'drivers/gpu/drm/amd/display') diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 5f56cc13d6dc..af40ea5765f4 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -1328,14 +1328,21 @@ void dcn10_init_hw(struct dc *dc) enum dc_status status = DC_ERROR_UNEXPECTED; for (i = 0; i < dc->link_count; i++) { - if (dc->links[i]->connector_signal != SIGNAL_TYPE_DISPLAY_PORT) { + if (dc->links[i]->connector_signal != SIGNAL_TYPE_DISPLAY_PORT) continue; - } - /* if any of the displays are lit up turn them off */ - status = core_link_read_dpcd(dc->links[i], DP_SET_POWER, - &dpcd_power_state, sizeof(dpcd_power_state)); - if (status == DC_OK && dpcd_power_state == DP_POWER_STATE_D0) { - dp_receiver_power_ctrl(dc->links[i], false); + + /* + * core_link_read_dpcd() will invoke dm_helpers_dp_read_dpcd(), + * which needs to read dpcd info with the help of aconnector. + * If aconnector (dc->links[i]->prev) is NULL, then dpcd status + * cannot be read. + */ + if (dc->links[i]->priv) { + /* if any of the displays are lit up turn them off */ + status = core_link_read_dpcd(dc->links[i], DP_SET_POWER, + &dpcd_power_state, sizeof(dpcd_power_state)); + if (status == DC_OK && dpcd_power_state == DP_POWER_STATE_D0) + dp_receiver_power_ctrl(dc->links[i], false); } } } -- cgit From 6a6c4a4d459ecacc9013c45dcbf2bc9747fdbdbd Mon Sep 17 00:00:00 2001 From: Aric Cyr Date: Thu, 30 Jan 2020 14:46:53 -0500 Subject: drm/amd/display: dal_ddc_i2c_payloads_create can fail causing panic [Why] Since the i2c payload allocation can fail need to check return codes [How] Clean up i2c payload allocations and check for errors Signed-off-by: Aric Cyr Reviewed-by: Joshua Aberback Acked-by: Rodrigo Siqueira Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c | 52 +++++++++++------------ 1 file changed, 25 insertions(+), 27 deletions(-) (limited to 'drivers/gpu/drm/amd/display') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c index a5586f68b4da..256889eed93e 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c @@ -126,22 +126,16 @@ struct aux_payloads { struct vector payloads; }; -static struct i2c_payloads *dal_ddc_i2c_payloads_create(struct dc_context *ctx, uint32_t count) +static bool dal_ddc_i2c_payloads_create( + struct dc_context *ctx, + struct i2c_payloads *payloads, + uint32_t count) { - struct i2c_payloads *payloads; - - payloads = kzalloc(sizeof(struct i2c_payloads), GFP_KERNEL); - - if (!payloads) - return NULL; - if (dal_vector_construct( &payloads->payloads, ctx, count, sizeof(struct i2c_payload))) - return payloads; - - kfree(payloads); - return NULL; + return true; + return false; } static struct i2c_payload *dal_ddc_i2c_payloads_get(struct i2c_payloads *p) @@ -154,14 +148,12 @@ static uint32_t dal_ddc_i2c_payloads_get_count(struct i2c_payloads *p) return p->payloads.count; } -static void dal_ddc_i2c_payloads_destroy(struct i2c_payloads **p) +static void dal_ddc_i2c_payloads_destroy(struct i2c_payloads *p) { - if (!p || !*p) + if (!p) return; - dal_vector_destruct(&(*p)->payloads); - kfree(*p); - *p = NULL; + dal_vector_destruct(&p->payloads); } #define DDC_MIN(a, b) (((a) < (b)) ? (a) : (b)) @@ -524,9 +516,13 @@ bool dal_ddc_service_query_ddc_data( uint32_t payloads_num = write_payloads + read_payloads; + if (write_size > EDID_SEGMENT_SIZE || read_size > EDID_SEGMENT_SIZE) return false; + if (!payloads_num) + return false; + /*TODO: len of payload data for i2c and aux is uint8!!!!, * but we want to read 256 over i2c!!!!*/ if (dal_ddc_service_is_in_aux_transaction_mode(ddc)) { @@ -557,23 +553,25 @@ bool dal_ddc_service_query_ddc_data( ret = dal_ddc_submit_aux_command(ddc, &payload); } } else { - struct i2c_payloads *payloads = - dal_ddc_i2c_payloads_create(ddc->ctx, payloads_num); + struct i2c_command command = {0}; + struct i2c_payloads payloads; + + if (!dal_ddc_i2c_payloads_create(ddc->ctx, &payloads, payloads_num)) + return false; - struct i2c_command command = { - .payloads = dal_ddc_i2c_payloads_get(payloads), - .number_of_payloads = 0, - .engine = DDC_I2C_COMMAND_ENGINE, - .speed = ddc->ctx->dc->caps.i2c_speed_in_khz }; + command.payloads = dal_ddc_i2c_payloads_get(&payloads); + command.number_of_payloads = 0; + command.engine = DDC_I2C_COMMAND_ENGINE; + command.speed = ddc->ctx->dc->caps.i2c_speed_in_khz; dal_ddc_i2c_payloads_add( - payloads, address, write_size, write_buf, true); + &payloads, address, write_size, write_buf, true); dal_ddc_i2c_payloads_add( - payloads, address, read_size, read_buf, false); + &payloads, address, read_size, read_buf, false); command.number_of_payloads = - dal_ddc_i2c_payloads_get_count(payloads); + dal_ddc_i2c_payloads_get_count(&payloads); ret = dm_helpers_submit_i2c( ddc->ctx, -- cgit From 8144148f3dc7766fb7f39015dd0c05f0120b13db Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Wed, 29 Jan 2020 16:41:20 -0500 Subject: drm/amd/display: update scaling filters Currently there is a minor error in scaling filter coefficients caused by truncation to fit the HW registers.This error accummulates with increased taps, but has gone unnoticed due to vast majority of scaling being done with only 4 taps. Scaling filters are now updated using HW team's filter generator which has quantization error minimization built in. Signed-off-by: Dmytro Laktyushkin Reviewed-by: Jun Lei Acked-by: Rodrigo Siqueira Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/dce/dce_scl_filters.c | 2204 +++++++++++--------- .../drm/amd/display/dc/dce/dce_scl_filters_old.c | 25 + 2 files changed, 1290 insertions(+), 939 deletions(-) create mode 100644 drivers/gpu/drm/amd/display/dc/dce/dce_scl_filters_old.c (limited to 'drivers/gpu/drm/amd/display') diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_scl_filters.c b/drivers/gpu/drm/amd/display/dc/dce/dce_scl_filters.c index 48862bebf29e..7311f312369f 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_scl_filters.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_scl_filters.c @@ -22,1004 +22,1330 @@ * Authors: AMD * */ - #include "transform.h" +//========================================= +// = 2 +// = 16 +// = 0.833333 (input/output) +// = 0 +// = ModifiedLanczos +// = s1.10 +// = s1.12 +//========================================= static const uint16_t filter_2tap_16p[18] = { - 4096, 0, - 3840, 256, - 3584, 512, - 3328, 768, - 3072, 1024, - 2816, 1280, - 2560, 1536, - 2304, 1792, - 2048, 2048 + 0x1000, 0x0000, + 0x0FF0, 0x0010, + 0x0FB0, 0x0050, + 0x0F34, 0x00CC, + 0x0E68, 0x0198, + 0x0D44, 0x02BC, + 0x0BC4, 0x043C, + 0x09FC, 0x0604, + 0x0800, 0x0800 }; +//========================================= +// = 3 +// = 16 +// = 0.83333 (input/output) +// = 0 +// = ModifiedLanczos +// = 1.10 +// = 1.12 +//========================================= static const uint16_t filter_3tap_16p_upscale[27] = { - 2048, 2048, 0, - 1708, 2424, 16348, - 1372, 2796, 16308, - 1056, 3148, 16272, - 768, 3464, 16244, - 512, 3728, 16236, - 296, 3928, 16252, - 124, 4052, 16296, - 0, 4096, 0 + 0x0804, 0x07FC, 0x0000, + 0x06AC, 0x0978, 0x3FDC, + 0x055C, 0x0AF0, 0x3FB4, + 0x0420, 0x0C50, 0x3F90, + 0x0300, 0x0D88, 0x3F78, + 0x0200, 0x0E90, 0x3F70, + 0x0128, 0x0F5C, 0x3F7C, + 0x007C, 0x0FD8, 0x3FAC, + 0x0000, 0x1000, 0x0000 }; -static const uint16_t filter_3tap_16p_117[27] = { - 2048, 2048, 0, - 1824, 2276, 16376, - 1600, 2496, 16380, - 1376, 2700, 16, - 1156, 2880, 52, - 948, 3032, 108, - 756, 3144, 192, - 580, 3212, 296, - 428, 3236, 428 +//========================================= +// = 3 +// = 16 +// = 1.16666 (input/output) +// = 0 +// = ModifiedLanczos +// = 1.10 +// = 1.12 +//========================================= +static const uint16_t filter_3tap_16p_116[27] = { + 0x0804, 0x07FC, 0x0000, + 0x0700, 0x0914, 0x3FEC, + 0x0604, 0x0A1C, 0x3FE0, + 0x050C, 0x0B14, 0x3FE0, + 0x041C, 0x0BF4, 0x3FF0, + 0x0340, 0x0CB0, 0x0010, + 0x0274, 0x0D3C, 0x0050, + 0x01C0, 0x0D94, 0x00AC, + 0x0128, 0x0DB4, 0x0124 }; -static const uint16_t filter_3tap_16p_150[27] = { - 2048, 2048, 0, - 1872, 2184, 36, - 1692, 2308, 88, - 1516, 2420, 156, - 1340, 2516, 236, - 1168, 2592, 328, - 1004, 2648, 440, - 844, 2684, 560, - 696, 2696, 696 +//========================================= +// = 3 +// = 16 +// = 1.49999 (input/output) +// = 0 +// = ModifiedLanczos +// = 1.10 +// = 1.12 +//========================================= +static const uint16_t filter_3tap_16p_149[27] = { + 0x0804, 0x07FC, 0x0000, + 0x0730, 0x08CC, 0x0004, + 0x0660, 0x098C, 0x0014, + 0x0590, 0x0A3C, 0x0034, + 0x04C4, 0x0AD4, 0x0068, + 0x0400, 0x0B54, 0x00AC, + 0x0348, 0x0BB0, 0x0108, + 0x029C, 0x0BEC, 0x0178, + 0x0200, 0x0C00, 0x0200 }; +//========================================= +// = 3 +// = 16 +// = 1.83332 (input/output) +// = 0 +// = ModifiedLanczos +// = 1.10 +// = 1.12 +//========================================= static const uint16_t filter_3tap_16p_183[27] = { - 2048, 2048, 0, - 1892, 2104, 92, - 1744, 2152, 196, - 1592, 2196, 300, - 1448, 2232, 412, - 1304, 2256, 528, - 1168, 2276, 648, - 1032, 2288, 772, - 900, 2292, 900 + 0x0804, 0x07FC, 0x0000, + 0x0754, 0x0880, 0x002C, + 0x06A8, 0x08F0, 0x0068, + 0x05FC, 0x0954, 0x00B0, + 0x0550, 0x09AC, 0x0104, + 0x04A8, 0x09F0, 0x0168, + 0x0408, 0x0A20, 0x01D8, + 0x036C, 0x0A40, 0x0254, + 0x02DC, 0x0A48, 0x02DC }; +//========================================= +// = 4 +// = 16 +// = 0.83333 (input/output) +// = 0 +// = ModifiedLanczos +// = 1.10 +// = 1.12 +//========================================= static const uint16_t filter_4tap_16p_upscale[36] = { - 0, 4096, 0, 0, - 16240, 4056, 180, 16380, - 16136, 3952, 404, 16364, - 16072, 3780, 664, 16344, - 16040, 3556, 952, 16312, - 16036, 3284, 1268, 16272, - 16052, 2980, 1604, 16224, - 16084, 2648, 1952, 16176, - 16128, 2304, 2304, 16128 + 0x0000, 0x1000, 0x0000, 0x0000, + 0x3F74, 0x0FDC, 0x00B4, 0x3FFC, + 0x3F0C, 0x0F70, 0x0194, 0x3FF0, + 0x3ECC, 0x0EC4, 0x0298, 0x3FD8, + 0x3EAC, 0x0DE4, 0x03B8, 0x3FB8, + 0x3EA4, 0x0CD8, 0x04F4, 0x3F90, + 0x3EB8, 0x0BA0, 0x0644, 0x3F64, + 0x3ED8, 0x0A54, 0x07A0, 0x3F34, + 0x3F00, 0x08FC, 0x0900, 0x3F04 }; -static const uint16_t filter_4tap_16p_117[36] = { - 428, 3236, 428, 0, - 276, 3232, 604, 16364, - 148, 3184, 800, 16340, - 44, 3104, 1016, 16312, - 16344, 2984, 1244, 16284, - 16284, 2832, 1488, 16256, - 16244, 2648, 1732, 16236, - 16220, 2440, 1976, 16220, - 16212, 2216, 2216, 16212 +//========================================= +// = 4 +// = 16 +// = 1.16666 (input/output) +// = 0 +// = ModifiedLanczos +// = 1.10 +// = 1.12 +//========================================= +static const uint16_t filter_4tap_16p_116[36] = { + 0x01A8, 0x0CB4, 0x01A4, 0x0000, + 0x0110, 0x0CB0, 0x0254, 0x3FEC, + 0x0090, 0x0C80, 0x031C, 0x3FD4, + 0x0024, 0x0C2C, 0x03F4, 0x3FBC, + 0x3FD8, 0x0BAC, 0x04DC, 0x3FA0, + 0x3F9C, 0x0B14, 0x05CC, 0x3F84, + 0x3F70, 0x0A60, 0x06C4, 0x3F6C, + 0x3F5C, 0x098C, 0x07BC, 0x3F5C, + 0x3F54, 0x08AC, 0x08AC, 0x3F54 }; -static const uint16_t filter_4tap_16p_150[36] = { - 696, 2700, 696, 0, - 560, 2700, 848, 16364, - 436, 2676, 1008, 16348, - 328, 2628, 1180, 16336, - 232, 2556, 1356, 16328, - 152, 2460, 1536, 16328, - 84, 2344, 1716, 16332, - 28, 2208, 1888, 16348, - 16376, 2052, 2052, 16376 +//========================================= +// = 4 +// = 16 +// = 1.49999 (input/output) +// = 0 +// = ModifiedLanczos +// = 1.10 +// = 1.12 +//========================================= +static const uint16_t filter_4tap_16p_149[36] = { + 0x02B8, 0x0A90, 0x02B8, 0x0000, + 0x0230, 0x0A90, 0x0350, 0x3FF0, + 0x01B8, 0x0A78, 0x03F0, 0x3FE0, + 0x0148, 0x0A48, 0x049C, 0x3FD4, + 0x00E8, 0x0A00, 0x054C, 0x3FCC, + 0x0098, 0x09A0, 0x0600, 0x3FC8, + 0x0054, 0x0928, 0x06B4, 0x3FD0, + 0x001C, 0x08A4, 0x0760, 0x3FE0, + 0x3FFC, 0x0804, 0x0804, 0x3FFC }; +//========================================= +// = 4 +// = 16 +// = 1.83332 (input/output) +// = 0 +// = ModifiedLanczos +// = 1.10 +// = 1.12 +//========================================= static const uint16_t filter_4tap_16p_183[36] = { - 940, 2208, 940, 0, - 832, 2200, 1052, 4, - 728, 2180, 1164, 16, - 628, 2148, 1280, 36, - 536, 2100, 1392, 60, - 448, 2044, 1504, 92, - 368, 1976, 1612, 132, - 296, 1900, 1716, 176, - 232, 1812, 1812, 232 + 0x03B0, 0x08A0, 0x03B0, 0x0000, + 0x0348, 0x0898, 0x041C, 0x0004, + 0x02DC, 0x0884, 0x0490, 0x0010, + 0x0278, 0x0864, 0x0500, 0x0024, + 0x021C, 0x0838, 0x0570, 0x003C, + 0x01C8, 0x07FC, 0x05E0, 0x005C, + 0x0178, 0x07B8, 0x064C, 0x0084, + 0x0130, 0x076C, 0x06B0, 0x00B4, + 0x00F0, 0x0714, 0x0710, 0x00EC }; +//========================================= +// = 2 +// = 64 +// = 0.833333 (input/output) +// = 0 +// = ModifiedLanczos +// = s1.10 +// = s1.12 +//========================================= static const uint16_t filter_2tap_64p[66] = { - 4096, 0, - 4032, 64, - 3968, 128, - 3904, 192, - 3840, 256, - 3776, 320, - 3712, 384, - 3648, 448, - 3584, 512, - 3520, 576, - 3456, 640, - 3392, 704, - 3328, 768, - 3264, 832, - 3200, 896, - 3136, 960, - 3072, 1024, - 3008, 1088, - 2944, 1152, - 2880, 1216, - 2816, 1280, - 2752, 1344, - 2688, 1408, - 2624, 1472, - 2560, 1536, - 2496, 1600, - 2432, 1664, - 2368, 1728, - 2304, 1792, - 2240, 1856, - 2176, 1920, - 2112, 1984, - 2048, 2048 }; + 0x1000, 0x0000, + 0x1000, 0x0000, + 0x0FFC, 0x0004, + 0x0FF8, 0x0008, + 0x0FF0, 0x0010, + 0x0FE4, 0x001C, + 0x0FD8, 0x0028, + 0x0FC4, 0x003C, + 0x0FB0, 0x0050, + 0x0F98, 0x0068, + 0x0F7C, 0x0084, + 0x0F58, 0x00A8, + 0x0F34, 0x00CC, + 0x0F08, 0x00F8, + 0x0ED8, 0x0128, + 0x0EA4, 0x015C, + 0x0E68, 0x0198, + 0x0E28, 0x01D8, + 0x0DE4, 0x021C, + 0x0D98, 0x0268, + 0x0D44, 0x02BC, + 0x0CEC, 0x0314, + 0x0C90, 0x0370, + 0x0C2C, 0x03D4, + 0x0BC4, 0x043C, + 0x0B58, 0x04A8, + 0x0AE8, 0x0518, + 0x0A74, 0x058C, + 0x09FC, 0x0604, + 0x0980, 0x0680, + 0x0900, 0x0700, + 0x0880, 0x0780, + 0x0800, 0x0800 +}; +//========================================= +// = 3 +// = 64 +// = 0.83333 (input/output) +// = 0 +// = ModifiedLanczos +// = 1.10 +// = 1.12 +//========================================= static const uint16_t filter_3tap_64p_upscale[99] = { - 2048, 2048, 0, - 1960, 2140, 16376, - 1876, 2236, 16364, - 1792, 2328, 16356, - 1708, 2424, 16348, - 1620, 2516, 16336, - 1540, 2612, 16328, - 1456, 2704, 16316, - 1372, 2796, 16308, - 1292, 2884, 16296, - 1212, 2976, 16288, - 1136, 3060, 16280, - 1056, 3148, 16272, - 984, 3228, 16264, - 908, 3312, 16256, - 836, 3388, 16248, - 768, 3464, 16244, - 700, 3536, 16240, - 636, 3604, 16236, - 572, 3668, 16236, - 512, 3728, 16236, - 456, 3784, 16236, - 400, 3836, 16240, - 348, 3884, 16244, - 296, 3928, 16252, - 252, 3964, 16260, - 204, 4000, 16268, - 164, 4028, 16284, - 124, 4052, 16296, - 88, 4072, 16316, - 56, 4084, 16336, - 24, 4092, 16356, - 0, 4096, 0 + 0x0804, 0x07FC, 0x0000, + 0x07A8, 0x0860, 0x3FF8, + 0x0754, 0x08BC, 0x3FF0, + 0x0700, 0x0918, 0x3FE8, + 0x06AC, 0x0978, 0x3FDC, + 0x0654, 0x09D8, 0x3FD4, + 0x0604, 0x0A34, 0x3FC8, + 0x05B0, 0x0A90, 0x3FC0, + 0x055C, 0x0AF0, 0x3FB4, + 0x050C, 0x0B48, 0x3FAC, + 0x04BC, 0x0BA0, 0x3FA4, + 0x0470, 0x0BF4, 0x3F9C, + 0x0420, 0x0C50, 0x3F90, + 0x03D8, 0x0C9C, 0x3F8C, + 0x038C, 0x0CF0, 0x3F84, + 0x0344, 0x0D40, 0x3F7C, + 0x0300, 0x0D88, 0x3F78, + 0x02BC, 0x0DD0, 0x3F74, + 0x027C, 0x0E14, 0x3F70, + 0x023C, 0x0E54, 0x3F70, + 0x0200, 0x0E90, 0x3F70, + 0x01C8, 0x0EC8, 0x3F70, + 0x0190, 0x0EFC, 0x3F74, + 0x015C, 0x0F2C, 0x3F78, + 0x0128, 0x0F5C, 0x3F7C, + 0x00FC, 0x0F7C, 0x3F88, + 0x00CC, 0x0FA4, 0x3F90, + 0x00A4, 0x0FC0, 0x3F9C, + 0x007C, 0x0FD8, 0x3FAC, + 0x0058, 0x0FE8, 0x3FC0, + 0x0038, 0x0FF4, 0x3FD4, + 0x0018, 0x1000, 0x3FE8, + 0x0000, 0x1000, 0x0000 }; -static const uint16_t filter_3tap_64p_117[99] = { - 2048, 2048, 0, - 1992, 2104, 16380, - 1936, 2160, 16380, - 1880, 2220, 16376, - 1824, 2276, 16376, - 1768, 2332, 16376, - 1712, 2388, 16376, - 1656, 2444, 16376, - 1600, 2496, 16380, - 1544, 2548, 0, - 1488, 2600, 4, - 1432, 2652, 8, - 1376, 2700, 16, - 1320, 2748, 20, - 1264, 2796, 32, - 1212, 2840, 40, - 1156, 2880, 52, - 1104, 2920, 64, - 1052, 2960, 80, - 1000, 2996, 92, - 948, 3032, 108, - 900, 3060, 128, - 852, 3092, 148, - 804, 3120, 168, - 756, 3144, 192, - 712, 3164, 216, - 668, 3184, 240, - 624, 3200, 268, - 580, 3212, 296, - 540, 3220, 328, - 500, 3228, 360, - 464, 3232, 392, - 428, 3236, 428 +//========================================= +// = 3 +// = 64 +// = 1.16666 (input/output) +// = 0 +// = ModifiedLanczos +// = 1.10 +// = 1.12 +//========================================= +static const uint16_t filter_3tap_64p_116[99] = { + 0x0804, 0x07FC, 0x0000, + 0x07C0, 0x0844, 0x3FFC, + 0x0780, 0x0888, 0x3FF8, + 0x0740, 0x08D0, 0x3FF0, + 0x0700, 0x0914, 0x3FEC, + 0x06C0, 0x0958, 0x3FE8, + 0x0684, 0x0998, 0x3FE4, + 0x0644, 0x09DC, 0x3FE0, + 0x0604, 0x0A1C, 0x3FE0, + 0x05C4, 0x0A5C, 0x3FE0, + 0x0588, 0x0A9C, 0x3FDC, + 0x0548, 0x0ADC, 0x3FDC, + 0x050C, 0x0B14, 0x3FE0, + 0x04CC, 0x0B54, 0x3FE0, + 0x0490, 0x0B8C, 0x3FE4, + 0x0458, 0x0BC0, 0x3FE8, + 0x041C, 0x0BF4, 0x3FF0, + 0x03E0, 0x0C28, 0x3FF8, + 0x03A8, 0x0C58, 0x0000, + 0x0374, 0x0C88, 0x0004, + 0x0340, 0x0CB0, 0x0010, + 0x0308, 0x0CD8, 0x0020, + 0x02D8, 0x0CFC, 0x002C, + 0x02A0, 0x0D20, 0x0040, + 0x0274, 0x0D3C, 0x0050, + 0x0244, 0x0D58, 0x0064, + 0x0214, 0x0D70, 0x007C, + 0x01E8, 0x0D84, 0x0094, + 0x01C0, 0x0D94, 0x00AC, + 0x0198, 0x0DA0, 0x00C8, + 0x0170, 0x0DAC, 0x00E4, + 0x014C, 0x0DB0, 0x0104, + 0x0128, 0x0DB4, 0x0124 }; -static const uint16_t filter_3tap_64p_150[99] = { - 2048, 2048, 0, - 2004, 2080, 8, - 1960, 2116, 16, - 1916, 2148, 28, - 1872, 2184, 36, - 1824, 2216, 48, - 1780, 2248, 60, - 1736, 2280, 76, - 1692, 2308, 88, - 1648, 2336, 104, - 1604, 2368, 120, - 1560, 2392, 136, - 1516, 2420, 156, - 1472, 2444, 172, - 1428, 2472, 192, - 1384, 2492, 212, - 1340, 2516, 236, - 1296, 2536, 256, - 1252, 2556, 280, - 1212, 2576, 304, - 1168, 2592, 328, - 1124, 2608, 356, - 1084, 2624, 384, - 1044, 2636, 412, - 1004, 2648, 440, - 964, 2660, 468, - 924, 2668, 500, - 884, 2676, 528, - 844, 2684, 560, - 808, 2688, 596, - 768, 2692, 628, - 732, 2696, 664, - 696, 2696, 696 +//========================================= +// = 3 +// = 64 +// = 1.49999 (input/output) +// = 0 +// = ModifiedLanczos +// = 1.10 +// = 1.12 +//========================================= +static const uint16_t filter_3tap_64p_149[99] = { + 0x0804, 0x07FC, 0x0000, + 0x07CC, 0x0834, 0x0000, + 0x0798, 0x0868, 0x0000, + 0x0764, 0x089C, 0x0000, + 0x0730, 0x08CC, 0x0004, + 0x0700, 0x08FC, 0x0004, + 0x06CC, 0x092C, 0x0008, + 0x0698, 0x095C, 0x000C, + 0x0660, 0x098C, 0x0014, + 0x062C, 0x09B8, 0x001C, + 0x05FC, 0x09E4, 0x0020, + 0x05C4, 0x0A10, 0x002C, + 0x0590, 0x0A3C, 0x0034, + 0x055C, 0x0A64, 0x0040, + 0x0528, 0x0A8C, 0x004C, + 0x04F8, 0x0AB0, 0x0058, + 0x04C4, 0x0AD4, 0x0068, + 0x0490, 0x0AF8, 0x0078, + 0x0460, 0x0B18, 0x0088, + 0x0430, 0x0B38, 0x0098, + 0x0400, 0x0B54, 0x00AC, + 0x03D0, 0x0B6C, 0x00C4, + 0x03A0, 0x0B88, 0x00D8, + 0x0374, 0x0B9C, 0x00F0, + 0x0348, 0x0BB0, 0x0108, + 0x0318, 0x0BC4, 0x0124, + 0x02EC, 0x0BD4, 0x0140, + 0x02C4, 0x0BE0, 0x015C, + 0x029C, 0x0BEC, 0x0178, + 0x0274, 0x0BF4, 0x0198, + 0x024C, 0x0BFC, 0x01B8, + 0x0228, 0x0BFC, 0x01DC, + 0x0200, 0x0C00, 0x0200 }; +//========================================= +// = 3 +// = 64 +// = 1.83332 (input/output) +// = 0 +// = ModifiedLanczos +// = 1.10 +// = 1.12 +//========================================= static const uint16_t filter_3tap_64p_183[99] = { - 2048, 2048, 0, - 2008, 2060, 20, - 1968, 2076, 44, - 1932, 2088, 68, - 1892, 2104, 92, - 1856, 2116, 120, - 1816, 2128, 144, - 1780, 2140, 168, - 1744, 2152, 196, - 1704, 2164, 220, - 1668, 2176, 248, - 1632, 2188, 272, - 1592, 2196, 300, - 1556, 2204, 328, - 1520, 2216, 356, - 1484, 2224, 384, - 1448, 2232, 412, - 1412, 2240, 440, - 1376, 2244, 468, - 1340, 2252, 496, - 1304, 2256, 528, - 1272, 2264, 556, - 1236, 2268, 584, - 1200, 2272, 616, - 1168, 2276, 648, - 1132, 2280, 676, - 1100, 2284, 708, - 1064, 2288, 740, - 1032, 2288, 772, - 996, 2292, 800, - 964, 2292, 832, - 932, 2292, 868, - 900, 2292, 900 + 0x0804, 0x07FC, 0x0000, + 0x07D4, 0x0824, 0x0008, + 0x07AC, 0x0840, 0x0014, + 0x0780, 0x0860, 0x0020, + 0x0754, 0x0880, 0x002C, + 0x0728, 0x089C, 0x003C, + 0x0700, 0x08B8, 0x0048, + 0x06D4, 0x08D4, 0x0058, + 0x06A8, 0x08F0, 0x0068, + 0x067C, 0x090C, 0x0078, + 0x0650, 0x0924, 0x008C, + 0x0628, 0x093C, 0x009C, + 0x05FC, 0x0954, 0x00B0, + 0x05D0, 0x096C, 0x00C4, + 0x05A8, 0x0980, 0x00D8, + 0x0578, 0x0998, 0x00F0, + 0x0550, 0x09AC, 0x0104, + 0x0528, 0x09BC, 0x011C, + 0x04FC, 0x09D0, 0x0134, + 0x04D4, 0x09E0, 0x014C, + 0x04A8, 0x09F0, 0x0168, + 0x0480, 0x09FC, 0x0184, + 0x045C, 0x0A08, 0x019C, + 0x0434, 0x0A14, 0x01B8, + 0x0408, 0x0A20, 0x01D8, + 0x03E0, 0x0A2C, 0x01F4, + 0x03B8, 0x0A34, 0x0214, + 0x0394, 0x0A38, 0x0234, + 0x036C, 0x0A40, 0x0254, + 0x0348, 0x0A44, 0x0274, + 0x0324, 0x0A48, 0x0294, + 0x0300, 0x0A48, 0x02B8, + 0x02DC, 0x0A48, 0x02DC }; +//========================================= +// = 4 +// = 64 +// = 0.83333 (input/output) +// = 0 +// = ModifiedLanczos +// = 1.10 +// = 1.12 +//========================================= static const uint16_t filter_4tap_64p_upscale[132] = { - 0, 4096, 0, 0, - 16344, 4092, 40, 0, - 16308, 4084, 84, 16380, - 16272, 4072, 132, 16380, - 16240, 4056, 180, 16380, - 16212, 4036, 232, 16376, - 16184, 4012, 288, 16372, - 16160, 3984, 344, 16368, - 16136, 3952, 404, 16364, - 16116, 3916, 464, 16360, - 16100, 3872, 528, 16356, - 16084, 3828, 596, 16348, - 16072, 3780, 664, 16344, - 16060, 3728, 732, 16336, - 16052, 3676, 804, 16328, - 16044, 3616, 876, 16320, - 16040, 3556, 952, 16312, - 16036, 3492, 1028, 16300, - 16032, 3424, 1108, 16292, - 16032, 3356, 1188, 16280, - 16036, 3284, 1268, 16272, - 16036, 3212, 1352, 16260, - 16040, 3136, 1436, 16248, - 16044, 3056, 1520, 16236, - 16052, 2980, 1604, 16224, - 16060, 2896, 1688, 16212, - 16064, 2816, 1776, 16200, - 16076, 2732, 1864, 16188, - 16084, 2648, 1952, 16176, - 16092, 2564, 2040, 16164, - 16104, 2476, 2128, 16152, - 16116, 2388, 2216, 16140, - 16128, 2304, 2304, 16128 }; + 0x0000, 0x1000, 0x0000, 0x0000, + 0x3FDC, 0x0FFC, 0x0028, 0x0000, + 0x3FB4, 0x0FF8, 0x0054, 0x0000, + 0x3F94, 0x0FE8, 0x0084, 0x0000, + 0x3F74, 0x0FDC, 0x00B4, 0x3FFC, + 0x3F58, 0x0FC4, 0x00E8, 0x3FFC, + 0x3F3C, 0x0FAC, 0x0120, 0x3FF8, + 0x3F24, 0x0F90, 0x0158, 0x3FF4, + 0x3F0C, 0x0F70, 0x0194, 0x3FF0, + 0x3EF8, 0x0F4C, 0x01D0, 0x3FEC, + 0x3EE8, 0x0F20, 0x0210, 0x3FE8, + 0x3ED8, 0x0EF4, 0x0254, 0x3FE0, + 0x3ECC, 0x0EC4, 0x0298, 0x3FD8, + 0x3EC0, 0x0E90, 0x02DC, 0x3FD4, + 0x3EB8, 0x0E58, 0x0324, 0x3FCC, + 0x3EB0, 0x0E20, 0x036C, 0x3FC4, + 0x3EAC, 0x0DE4, 0x03B8, 0x3FB8, + 0x3EA8, 0x0DA4, 0x0404, 0x3FB0, + 0x3EA4, 0x0D60, 0x0454, 0x3FA8, + 0x3EA4, 0x0D1C, 0x04A4, 0x3F9C, + 0x3EA4, 0x0CD8, 0x04F4, 0x3F90, + 0x3EA8, 0x0C88, 0x0548, 0x3F88, + 0x3EAC, 0x0C3C, 0x059C, 0x3F7C, + 0x3EB0, 0x0BF0, 0x05F0, 0x3F70, + 0x3EB8, 0x0BA0, 0x0644, 0x3F64, + 0x3EBC, 0x0B54, 0x0698, 0x3F58, + 0x3EC4, 0x0B00, 0x06F0, 0x3F4C, + 0x3ECC, 0x0AAC, 0x0748, 0x3F40, + 0x3ED8, 0x0A54, 0x07A0, 0x3F34, + 0x3EE0, 0x0A04, 0x07F8, 0x3F24, + 0x3EEC, 0x09AC, 0x0850, 0x3F18, + 0x3EF8, 0x0954, 0x08A8, 0x3F0C, + 0x3F00, 0x08FC, 0x0900, 0x3F04 +}; -static const uint16_t filter_4tap_64p_117[132] = { - 420, 3248, 420, 0, - 380, 3248, 464, 16380, - 344, 3248, 508, 16372, - 308, 3248, 552, 16368, - 272, 3240, 596, 16364, - 236, 3236, 644, 16356, - 204, 3224, 692, 16352, - 172, 3212, 744, 16344, - 144, 3196, 796, 16340, - 116, 3180, 848, 16332, - 88, 3160, 900, 16324, - 60, 3136, 956, 16320, - 36, 3112, 1012, 16312, - 16, 3084, 1068, 16304, - 16380, 3056, 1124, 16296, - 16360, 3024, 1184, 16292, - 16340, 2992, 1244, 16284, - 16324, 2956, 1304, 16276, - 16308, 2920, 1364, 16268, - 16292, 2880, 1424, 16264, - 16280, 2836, 1484, 16256, - 16268, 2792, 1548, 16252, - 16256, 2748, 1608, 16244, - 16248, 2700, 1668, 16240, - 16240, 2652, 1732, 16232, - 16232, 2604, 1792, 16228, - 16228, 2552, 1856, 16224, - 16220, 2500, 1916, 16220, - 16216, 2444, 1980, 16216, - 16216, 2388, 2040, 16216, - 16212, 2332, 2100, 16212, - 16212, 2276, 2160, 16212, - 16212, 2220, 2220, 16212 }; +//========================================= +// = 4 +// = 64 +// = 1.16666 (input/output) +// = 0 +// = ModifiedLanczos +// = 1.10 +// = 1.12 +//========================================= +static const uint16_t filter_4tap_64p_116[132] = { + 0x01A8, 0x0CB4, 0x01A4, 0x0000, + 0x017C, 0x0CB8, 0x01D0, 0x3FFC, + 0x0158, 0x0CB8, 0x01F8, 0x3FF8, + 0x0130, 0x0CB4, 0x0228, 0x3FF4, + 0x0110, 0x0CB0, 0x0254, 0x3FEC, + 0x00EC, 0x0CA8, 0x0284, 0x3FE8, + 0x00CC, 0x0C9C, 0x02B4, 0x3FE4, + 0x00AC, 0x0C90, 0x02E8, 0x3FDC, + 0x0090, 0x0C80, 0x031C, 0x3FD4, + 0x0070, 0x0C70, 0x0350, 0x3FD0, + 0x0058, 0x0C5C, 0x0384, 0x3FC8, + 0x003C, 0x0C48, 0x03BC, 0x3FC0, + 0x0024, 0x0C2C, 0x03F4, 0x3FBC, + 0x0010, 0x0C10, 0x042C, 0x3FB4, + 0x3FFC, 0x0BF4, 0x0464, 0x3FAC, + 0x3FE8, 0x0BD4, 0x04A0, 0x3FA4, + 0x3FD8, 0x0BAC, 0x04DC, 0x3FA0, + 0x3FC4, 0x0B8C, 0x0518, 0x3F98, + 0x3FB4, 0x0B68, 0x0554, 0x3F90, + 0x3FA8, 0x0B40, 0x0590, 0x3F88, + 0x3F9C, 0x0B14, 0x05CC, 0x3F84, + 0x3F90, 0x0AEC, 0x0608, 0x3F7C, + 0x3F84, 0x0ABC, 0x0648, 0x3F78, + 0x3F7C, 0x0A90, 0x0684, 0x3F70, + 0x3F70, 0x0A60, 0x06C4, 0x3F6C, + 0x3F6C, 0x0A2C, 0x0700, 0x3F68, + 0x3F64, 0x09F8, 0x0740, 0x3F64, + 0x3F60, 0x09C4, 0x077C, 0x3F60, + 0x3F5C, 0x098C, 0x07BC, 0x3F5C, + 0x3F58, 0x0958, 0x07F8, 0x3F58, + 0x3F58, 0x091C, 0x0834, 0x3F58, + 0x3F54, 0x08E4, 0x0870, 0x3F58, + 0x3F54, 0x08AC, 0x08AC, 0x3F54 +}; -static const uint16_t filter_4tap_64p_150[132] = { - 696, 2700, 696, 0, - 660, 2704, 732, 16380, - 628, 2704, 768, 16376, - 596, 2704, 804, 16372, - 564, 2700, 844, 16364, - 532, 2696, 884, 16360, - 500, 2692, 924, 16356, - 472, 2684, 964, 16352, - 440, 2676, 1004, 16352, - 412, 2668, 1044, 16348, - 384, 2656, 1088, 16344, - 360, 2644, 1128, 16340, - 332, 2632, 1172, 16336, - 308, 2616, 1216, 16336, - 284, 2600, 1260, 16332, - 260, 2580, 1304, 16332, - 236, 2560, 1348, 16328, - 216, 2540, 1392, 16328, - 196, 2516, 1436, 16328, - 176, 2492, 1480, 16324, - 156, 2468, 1524, 16324, - 136, 2440, 1568, 16328, - 120, 2412, 1612, 16328, - 104, 2384, 1656, 16328, - 88, 2352, 1700, 16332, - 72, 2324, 1744, 16332, - 60, 2288, 1788, 16336, - 48, 2256, 1828, 16340, - 36, 2220, 1872, 16344, - 24, 2184, 1912, 16352, - 12, 2148, 1952, 16356, - 4, 2112, 1996, 16364, - 16380, 2072, 2036, 16372 }; +//========================================= +// = 4 +// = 64 +// = 1.49999 (input/output) +// = 0 +// = ModifiedLanczos +// = 1.10 +// = 1.12 +//========================================= +static const uint16_t filter_4tap_64p_149[132] = { + 0x02B8, 0x0A90, 0x02B8, 0x0000, + 0x0294, 0x0A94, 0x02DC, 0x3FFC, + 0x0274, 0x0A94, 0x0300, 0x3FF8, + 0x0250, 0x0A94, 0x0328, 0x3FF4, + 0x0230, 0x0A90, 0x0350, 0x3FF0, + 0x0214, 0x0A8C, 0x0374, 0x3FEC, + 0x01F0, 0x0A88, 0x03A0, 0x3FE8, + 0x01D4, 0x0A80, 0x03C8, 0x3FE4, + 0x01B8, 0x0A78, 0x03F0, 0x3FE0, + 0x0198, 0x0A70, 0x041C, 0x3FDC, + 0x0180, 0x0A64, 0x0444, 0x3FD8, + 0x0164, 0x0A54, 0x0470, 0x3FD8, + 0x0148, 0x0A48, 0x049C, 0x3FD4, + 0x0130, 0x0A38, 0x04C8, 0x3FD0, + 0x0118, 0x0A24, 0x04F4, 0x3FD0, + 0x0100, 0x0A14, 0x0520, 0x3FCC, + 0x00E8, 0x0A00, 0x054C, 0x3FCC, + 0x00D4, 0x09E8, 0x057C, 0x3FC8, + 0x00C0, 0x09D0, 0x05A8, 0x3FC8, + 0x00AC, 0x09B8, 0x05D4, 0x3FC8, + 0x0098, 0x09A0, 0x0600, 0x3FC8, + 0x0084, 0x0984, 0x0630, 0x3FC8, + 0x0074, 0x0964, 0x065C, 0x3FCC, + 0x0064, 0x0948, 0x0688, 0x3FCC, + 0x0054, 0x0928, 0x06B4, 0x3FD0, + 0x0044, 0x0908, 0x06E0, 0x3FD4, + 0x0038, 0x08E8, 0x070C, 0x3FD4, + 0x002C, 0x08C4, 0x0738, 0x3FD8, + 0x001C, 0x08A4, 0x0760, 0x3FE0, + 0x0014, 0x087C, 0x078C, 0x3FE4, + 0x0008, 0x0858, 0x07B4, 0x3FEC, + 0x0000, 0x0830, 0x07DC, 0x3FF4, + 0x3FFC, 0x0804, 0x0804, 0x3FFC +}; +//========================================= +// = 4 +// = 64 +// = 1.83332 (input/output) +// = 0 +// = ModifiedLanczos +// = 1.10 +// = 1.12 +//========================================= static const uint16_t filter_4tap_64p_183[132] = { - 944, 2204, 944, 0, - 916, 2204, 972, 0, - 888, 2200, 996, 0, - 860, 2200, 1024, 4, - 832, 2196, 1052, 4, - 808, 2192, 1080, 8, - 780, 2188, 1108, 12, - 756, 2180, 1140, 12, - 728, 2176, 1168, 16, - 704, 2168, 1196, 20, - 680, 2160, 1224, 24, - 656, 2152, 1252, 28, - 632, 2144, 1280, 36, - 608, 2132, 1308, 40, - 584, 2120, 1336, 48, - 560, 2112, 1364, 52, - 536, 2096, 1392, 60, - 516, 2084, 1420, 68, - 492, 2072, 1448, 76, - 472, 2056, 1476, 84, - 452, 2040, 1504, 92, - 428, 2024, 1532, 100, - 408, 2008, 1560, 112, - 392, 1992, 1584, 120, - 372, 1972, 1612, 132, - 352, 1956, 1636, 144, - 336, 1936, 1664, 156, - 316, 1916, 1688, 168, - 300, 1896, 1712, 180, - 284, 1876, 1736, 192, - 268, 1852, 1760, 208, - 252, 1832, 1784, 220, - 236, 1808, 1808, 236 }; + 0x03B0, 0x08A0, 0x03B0, 0x0000, + 0x0394, 0x08A0, 0x03CC, 0x0000, + 0x037C, 0x089C, 0x03E8, 0x0000, + 0x0360, 0x089C, 0x0400, 0x0004, + 0x0348, 0x0898, 0x041C, 0x0004, + 0x032C, 0x0894, 0x0438, 0x0008, + 0x0310, 0x0890, 0x0454, 0x000C, + 0x02F8, 0x0888, 0x0474, 0x000C, + 0x02DC, 0x0884, 0x0490, 0x0010, + 0x02C4, 0x087C, 0x04AC, 0x0014, + 0x02AC, 0x0874, 0x04C8, 0x0018, + 0x0290, 0x086C, 0x04E4, 0x0020, + 0x0278, 0x0864, 0x0500, 0x0024, + 0x0264, 0x0858, 0x051C, 0x0028, + 0x024C, 0x084C, 0x0538, 0x0030, + 0x0234, 0x0844, 0x0554, 0x0034, + 0x021C, 0x0838, 0x0570, 0x003C, + 0x0208, 0x0828, 0x058C, 0x0044, + 0x01F0, 0x081C, 0x05A8, 0x004C, + 0x01DC, 0x080C, 0x05C4, 0x0054, + 0x01C8, 0x07FC, 0x05E0, 0x005C, + 0x01B4, 0x07EC, 0x05FC, 0x0064, + 0x019C, 0x07DC, 0x0618, 0x0070, + 0x018C, 0x07CC, 0x0630, 0x0078, + 0x0178, 0x07B8, 0x064C, 0x0084, + 0x0164, 0x07A8, 0x0664, 0x0090, + 0x0150, 0x0794, 0x0680, 0x009C, + 0x0140, 0x0780, 0x0698, 0x00A8, + 0x0130, 0x076C, 0x06B0, 0x00B4, + 0x0120, 0x0758, 0x06C8, 0x00C0, + 0x0110, 0x0740, 0x06E0, 0x00D0, + 0x0100, 0x072C, 0x06F8, 0x00DC, + 0x00F0, 0x0714, 0x0710, 0x00EC +}; +//========================================= +// = 5 +// = 64 +// = 0.83333 (input/output) +// = 0 +// = ModifiedLanczos +// = 1.10 +// = 1.12 +//========================================= static const uint16_t filter_5tap_64p_upscale[165] = { - 15936, 2496, 2496, 15936, 0, - 15948, 2404, 2580, 15924, 0, - 15960, 2312, 2664, 15912, 4, - 15976, 2220, 2748, 15904, 8, - 15992, 2128, 2832, 15896, 12, - 16004, 2036, 2912, 15888, 16, - 16020, 1944, 2992, 15880, 20, - 16036, 1852, 3068, 15876, 20, - 16056, 1760, 3140, 15876, 24, - 16072, 1668, 3216, 15872, 28, - 16088, 1580, 3284, 15872, 32, - 16104, 1492, 3352, 15876, 32, - 16120, 1404, 3420, 15876, 36, - 16140, 1316, 3480, 15884, 40, - 16156, 1228, 3540, 15892, 40, - 16172, 1144, 3600, 15900, 40, - 16188, 1060, 3652, 15908, 44, - 16204, 980, 3704, 15924, 44, - 16220, 900, 3756, 15936, 44, - 16236, 824, 3800, 15956, 44, - 16248, 744, 3844, 15972, 44, - 16264, 672, 3884, 15996, 44, - 16276, 600, 3920, 16020, 44, - 16292, 528, 3952, 16044, 40, - 16304, 460, 3980, 16072, 40, - 16316, 396, 4008, 16104, 36, - 16328, 332, 4032, 16136, 32, - 16336, 272, 4048, 16172, 28, - 16348, 212, 4064, 16208, 24, - 16356, 156, 4080, 16248, 16, - 16368, 100, 4088, 16292, 12, - 16376, 48, 4092, 16336, 4, - 0, 0, 4096, 0, 0 }; + 0x3E40, 0x09C0, 0x09C0, 0x3E40, 0x0000, + 0x3E50, 0x0964, 0x0A18, 0x3E34, 0x0000, + 0x3E5C, 0x0908, 0x0A6C, 0x3E2C, 0x0004, + 0x3E6C, 0x08AC, 0x0AC0, 0x3E20, 0x0008, + 0x3E78, 0x0850, 0x0B14, 0x3E18, 0x000C, + 0x3E88, 0x07F4, 0x0B60, 0x3E14, 0x0010, + 0x3E98, 0x0798, 0x0BB0, 0x3E0C, 0x0014, + 0x3EA8, 0x073C, 0x0C00, 0x3E08, 0x0014, + 0x3EB8, 0x06E4, 0x0C48, 0x3E04, 0x0018, + 0x3ECC, 0x0684, 0x0C90, 0x3E04, 0x001C, + 0x3EDC, 0x062C, 0x0CD4, 0x3E04, 0x0020, + 0x3EEC, 0x05D4, 0x0D1C, 0x3E04, 0x0020, + 0x3EFC, 0x057C, 0x0D5C, 0x3E08, 0x0024, + 0x3F0C, 0x0524, 0x0D98, 0x3E10, 0x0028, + 0x3F20, 0x04CC, 0x0DD8, 0x3E14, 0x0028, + 0x3F30, 0x0478, 0x0E14, 0x3E1C, 0x0028, + 0x3F40, 0x0424, 0x0E48, 0x3E28, 0x002C, + 0x3F50, 0x03D4, 0x0E7C, 0x3E34, 0x002C, + 0x3F60, 0x0384, 0x0EAC, 0x3E44, 0x002C, + 0x3F6C, 0x0338, 0x0EDC, 0x3E54, 0x002C, + 0x3F7C, 0x02E8, 0x0F08, 0x3E68, 0x002C, + 0x3F8C, 0x02A0, 0x0F2C, 0x3E7C, 0x002C, + 0x3F98, 0x0258, 0x0F50, 0x3E94, 0x002C, + 0x3FA4, 0x0210, 0x0F74, 0x3EB0, 0x0028, + 0x3FB0, 0x01CC, 0x0F90, 0x3ECC, 0x0028, + 0x3FC0, 0x018C, 0x0FA8, 0x3EE8, 0x0024, + 0x3FC8, 0x014C, 0x0FC0, 0x3F0C, 0x0020, + 0x3FD4, 0x0110, 0x0FD4, 0x3F2C, 0x001C, + 0x3FE0, 0x00D4, 0x0FE0, 0x3F54, 0x0018, + 0x3FE8, 0x009C, 0x0FF0, 0x3F7C, 0x0010, + 0x3FF0, 0x0064, 0x0FFC, 0x3FA4, 0x000C, + 0x3FFC, 0x0030, 0x0FFC, 0x3FD4, 0x0004, + 0x0000, 0x0000, 0x1000, 0x0000, 0x0000 +}; -static const uint16_t filter_5tap_64p_117[165] = { - 16056, 2372, 2372, 16056, 0, - 16052, 2312, 2432, 16060, 0, - 16052, 2252, 2488, 16064, 0, - 16052, 2188, 2548, 16072, 0, - 16052, 2124, 2600, 16076, 0, - 16052, 2064, 2656, 16088, 0, - 16052, 2000, 2708, 16096, 0, - 16056, 1932, 2760, 16108, 0, - 16060, 1868, 2808, 16120, 0, - 16064, 1804, 2856, 16132, 0, - 16068, 1740, 2904, 16148, 16380, - 16076, 1676, 2948, 16164, 16380, - 16080, 1612, 2992, 16180, 16376, - 16088, 1544, 3032, 16200, 16372, - 16096, 1480, 3072, 16220, 16372, - 16104, 1420, 3108, 16244, 16368, - 16112, 1356, 3144, 16268, 16364, - 16120, 1292, 3180, 16292, 16360, - 16128, 1232, 3212, 16320, 16356, - 16136, 1168, 3240, 16344, 16352, - 16144, 1108, 3268, 16376, 16344, - 16156, 1048, 3292, 20, 16340, - 16164, 988, 3316, 52, 16332, - 16172, 932, 3336, 88, 16328, - 16184, 872, 3356, 124, 16320, - 16192, 816, 3372, 160, 16316, - 16204, 760, 3388, 196, 16308, - 16212, 708, 3400, 236, 16300, - 16220, 656, 3412, 276, 16292, - 16232, 604, 3420, 320, 16284, - 16240, 552, 3424, 364, 16276, - 16248, 504, 3428, 408, 16268, - 16256, 456, 3428, 456, 16256 }; +//========================================= +// = 5 +// = 64 +// = 1.16666 (input/output) +// = 0 +// = ModifiedLanczos +// = 1.10 +// = 1.12 +//========================================= +static const uint16_t filter_5tap_64p_116[165] = { + 0x3EDC, 0x0924, 0x0924, 0x3EDC, 0x0000, + 0x3ED8, 0x08EC, 0x095C, 0x3EE0, 0x0000, + 0x3ED4, 0x08B0, 0x0994, 0x3EE8, 0x0000, + 0x3ED0, 0x0878, 0x09C8, 0x3EF0, 0x0000, + 0x3ED0, 0x083C, 0x09FC, 0x3EF8, 0x0000, + 0x3ED0, 0x0800, 0x0A2C, 0x3F04, 0x0000, + 0x3ED0, 0x07C4, 0x0A5C, 0x3F10, 0x0000, + 0x3ED0, 0x0788, 0x0A8C, 0x3F1C, 0x0000, + 0x3ED0, 0x074C, 0x0AC0, 0x3F28, 0x3FFC, + 0x3ED4, 0x0710, 0x0AE8, 0x3F38, 0x3FFC, + 0x3ED8, 0x06D0, 0x0B18, 0x3F48, 0x3FF8, + 0x3EDC, 0x0694, 0x0B3C, 0x3F5C, 0x3FF8, + 0x3EE0, 0x0658, 0x0B68, 0x3F6C, 0x3FF4, + 0x3EE4, 0x061C, 0x0B90, 0x3F80, 0x3FF0, + 0x3EEC, 0x05DC, 0x0BB4, 0x3F98, 0x3FEC, + 0x3EF0, 0x05A0, 0x0BD8, 0x3FB0, 0x3FE8, + 0x3EF8, 0x0564, 0x0BF8, 0x3FC8, 0x3FE4, + 0x3EFC, 0x0528, 0x0C1C, 0x3FE0, 0x3FE0, + 0x3F04, 0x04EC, 0x0C38, 0x3FFC, 0x3FDC, + 0x3F0C, 0x04B4, 0x0C54, 0x0014, 0x3FD8, + 0x3F14, 0x047C, 0x0C70, 0x0030, 0x3FD0, + 0x3F1C, 0x0440, 0x0C88, 0x0050, 0x3FCC, + 0x3F24, 0x0408, 0x0CA0, 0x0070, 0x3FC4, + 0x3F2C, 0x03D0, 0x0CB0, 0x0094, 0x3FC0, + 0x3F34, 0x0398, 0x0CC4, 0x00B8, 0x3FB8, + 0x3F3C, 0x0364, 0x0CD4, 0x00DC, 0x3FB0, + 0x3F48, 0x032C, 0x0CE0, 0x0100, 0x3FAC, + 0x3F50, 0x02F8, 0x0CEC, 0x0128, 0x3FA4, + 0x3F58, 0x02C4, 0x0CF8, 0x0150, 0x3F9C, + 0x3F60, 0x0290, 0x0D00, 0x017C, 0x3F94, + 0x3F68, 0x0260, 0x0D04, 0x01A8, 0x3F8C, + 0x3F74, 0x0230, 0x0D04, 0x01D4, 0x3F84, + 0x3F7C, 0x0200, 0x0D08, 0x0200, 0x3F7C +}; -static const uint16_t filter_5tap_64p_150[165] = { - 16368, 2064, 2064, 16368, 0, - 16352, 2028, 2100, 16380, 16380, - 16340, 1996, 2132, 12, 16376, - 16328, 1960, 2168, 24, 16376, - 16316, 1924, 2204, 44, 16372, - 16308, 1888, 2236, 60, 16368, - 16296, 1848, 2268, 76, 16364, - 16288, 1812, 2300, 96, 16360, - 16280, 1772, 2328, 116, 16356, - 16272, 1736, 2360, 136, 16352, - 16268, 1696, 2388, 160, 16348, - 16260, 1656, 2416, 180, 16344, - 16256, 1616, 2440, 204, 16340, - 16248, 1576, 2464, 228, 16336, - 16244, 1536, 2492, 252, 16332, - 16240, 1496, 2512, 276, 16324, - 16240, 1456, 2536, 304, 16320, - 16236, 1416, 2556, 332, 16316, - 16232, 1376, 2576, 360, 16312, - 16232, 1336, 2592, 388, 16308, - 16232, 1296, 2612, 416, 16300, - 16232, 1256, 2628, 448, 16296, - 16232, 1216, 2640, 480, 16292, - 16232, 1172, 2652, 512, 16288, - 16232, 1132, 2664, 544, 16284, - 16232, 1092, 2676, 576, 16280, - 16236, 1056, 2684, 608, 16272, - 16236, 1016, 2692, 644, 16268, - 16240, 976, 2700, 680, 16264, - 16240, 936, 2704, 712, 16260, - 16244, 900, 2708, 748, 16256, - 16248, 860, 2708, 788, 16252, - 16248, 824, 2708, 824, 16248 }; +//========================================= +// = 5 +// = 64 +// = 1.49999 (input/output) +// = 0 +// = ModifiedLanczos +// = 1.10 +// = 1.12 +//========================================= +static const uint16_t filter_5tap_64p_149[165] = { + 0x3FF4, 0x080C, 0x080C, 0x3FF4, 0x0000, + 0x3FE8, 0x07E8, 0x0830, 0x0000, 0x0000, + 0x3FDC, 0x07C8, 0x0850, 0x0010, 0x3FFC, + 0x3FD0, 0x07A4, 0x0878, 0x001C, 0x3FF8, + 0x3FC4, 0x0780, 0x0898, 0x0030, 0x3FF4, + 0x3FB8, 0x075C, 0x08B8, 0x0040, 0x3FF4, + 0x3FB0, 0x0738, 0x08D8, 0x0050, 0x3FF0, + 0x3FA8, 0x0710, 0x08F8, 0x0064, 0x3FEC, + 0x3FA0, 0x06EC, 0x0914, 0x0078, 0x3FE8, + 0x3F98, 0x06C4, 0x0934, 0x008C, 0x3FE4, + 0x3F90, 0x06A0, 0x094C, 0x00A4, 0x3FE0, + 0x3F8C, 0x0678, 0x0968, 0x00B8, 0x3FDC, + 0x3F84, 0x0650, 0x0984, 0x00D0, 0x3FD8, + 0x3F80, 0x0628, 0x099C, 0x00E8, 0x3FD4, + 0x3F7C, 0x0600, 0x09B8, 0x0100, 0x3FCC, + 0x3F78, 0x05D8, 0x09D0, 0x0118, 0x3FC8, + 0x3F74, 0x05B0, 0x09E4, 0x0134, 0x3FC4, + 0x3F70, 0x0588, 0x09F8, 0x0150, 0x3FC0, + 0x3F70, 0x0560, 0x0A08, 0x016C, 0x3FBC, + 0x3F6C, 0x0538, 0x0A20, 0x0188, 0x3FB4, + 0x3F6C, 0x0510, 0x0A30, 0x01A4, 0x3FB0, + 0x3F6C, 0x04E8, 0x0A3C, 0x01C4, 0x3FAC, + 0x3F6C, 0x04C0, 0x0A48, 0x01E4, 0x3FA8, + 0x3F6C, 0x0498, 0x0A58, 0x0200, 0x3FA4, + 0x3F6C, 0x0470, 0x0A60, 0x0224, 0x3FA0, + 0x3F6C, 0x0448, 0x0A70, 0x0244, 0x3F98, + 0x3F70, 0x0420, 0x0A78, 0x0264, 0x3F94, + 0x3F70, 0x03F8, 0x0A80, 0x0288, 0x3F90, + 0x3F74, 0x03D4, 0x0A84, 0x02A8, 0x3F8C, + 0x3F74, 0x03AC, 0x0A8C, 0x02CC, 0x3F88, + 0x3F78, 0x0384, 0x0A90, 0x02F0, 0x3F84, + 0x3F7C, 0x0360, 0x0A90, 0x0314, 0x3F80, + 0x3F7C, 0x033C, 0x0A90, 0x033C, 0x3F7C +}; +//========================================= +// = 5 +// = 64 +// = 1.83332 (input/output) +// = 0 +// = ModifiedLanczos +// = 1.10 +// = 1.12 +//========================================= static const uint16_t filter_5tap_64p_183[165] = { - 228, 1816, 1816, 228, 0, - 216, 1792, 1836, 248, 16380, - 200, 1772, 1860, 264, 16376, - 184, 1748, 1884, 280, 16376, - 168, 1728, 1904, 300, 16372, - 156, 1704, 1928, 316, 16368, - 144, 1680, 1948, 336, 16364, - 128, 1656, 1968, 356, 16364, - 116, 1632, 1988, 376, 16360, - 104, 1604, 2008, 396, 16356, - 96, 1580, 2024, 416, 16356, - 84, 1556, 2044, 440, 16352, - 72, 1528, 2060, 460, 16348, - 64, 1504, 2076, 484, 16348, - 52, 1476, 2092, 504, 16344, - 44, 1448, 2104, 528, 16344, - 36, 1424, 2120, 552, 16340, - 28, 1396, 2132, 576, 16340, - 20, 1368, 2144, 600, 16340, - 12, 1340, 2156, 624, 16336, - 4, 1312, 2168, 652, 16336, - 0, 1284, 2180, 676, 16336, - 16376, 1256, 2188, 700, 16332, - 16372, 1228, 2196, 728, 16332, - 16368, 1200, 2204, 752, 16332, - 16364, 1172, 2212, 780, 16332, - 16356, 1144, 2216, 808, 16332, - 16352, 1116, 2220, 836, 16332, - 16352, 1084, 2224, 860, 16332, - 16348, 1056, 2228, 888, 16336, - 16344, 1028, 2232, 916, 16336, - 16340, 1000, 2232, 944, 16336, - 16340, 972, 2232, 972, 16340 }; + 0x0168, 0x069C, 0x0698, 0x0164, 0x0000, + 0x0154, 0x068C, 0x06AC, 0x0174, 0x0000, + 0x0144, 0x0674, 0x06C0, 0x0188, 0x0000, + 0x0138, 0x0664, 0x06D0, 0x0198, 0x3FFC, + 0x0128, 0x0654, 0x06E0, 0x01A8, 0x3FFC, + 0x0118, 0x0640, 0x06F0, 0x01BC, 0x3FFC, + 0x010C, 0x0630, 0x0700, 0x01CC, 0x3FF8, + 0x00FC, 0x061C, 0x0710, 0x01E0, 0x3FF8, + 0x00F0, 0x060C, 0x071C, 0x01F0, 0x3FF8, + 0x00E4, 0x05F4, 0x072C, 0x0204, 0x3FF8, + 0x00D8, 0x05E4, 0x0738, 0x0218, 0x3FF4, + 0x00CC, 0x05D0, 0x0744, 0x022C, 0x3FF4, + 0x00C0, 0x05B8, 0x0754, 0x0240, 0x3FF4, + 0x00B4, 0x05A4, 0x0760, 0x0254, 0x3FF4, + 0x00A8, 0x0590, 0x076C, 0x0268, 0x3FF4, + 0x009C, 0x057C, 0x0778, 0x027C, 0x3FF4, + 0x0094, 0x0564, 0x0780, 0x0294, 0x3FF4, + 0x0088, 0x0550, 0x0788, 0x02A8, 0x3FF8, + 0x0080, 0x0538, 0x0794, 0x02BC, 0x3FF8, + 0x0074, 0x0524, 0x079C, 0x02D4, 0x3FF8, + 0x006C, 0x0510, 0x07A4, 0x02E8, 0x3FF8, + 0x0064, 0x04F4, 0x07AC, 0x0300, 0x3FFC, + 0x005C, 0x04E4, 0x07B0, 0x0314, 0x3FFC, + 0x0054, 0x04C8, 0x07B8, 0x032C, 0x0000, + 0x004C, 0x04B4, 0x07C0, 0x0340, 0x0000, + 0x0044, 0x04A0, 0x07C4, 0x0358, 0x0000, + 0x003C, 0x0488, 0x07C8, 0x0370, 0x0004, + 0x0038, 0x0470, 0x07CC, 0x0384, 0x0008, + 0x0030, 0x045C, 0x07D0, 0x039C, 0x0008, + 0x002C, 0x0444, 0x07D0, 0x03B4, 0x000C, + 0x0024, 0x042C, 0x07D4, 0x03CC, 0x0010, + 0x0020, 0x0414, 0x07D4, 0x03E0, 0x0018, + 0x001C, 0x03FC, 0x07D4, 0x03F8, 0x001C +}; +//========================================= +// = 6 +// = 64 +// = 0.83333 (input/output) +// = 0 +// = ModifiedLanczos +// = 1.10 +// = 1.12 +//========================================= static const uint16_t filter_6tap_64p_upscale[198] = { - 0, 0, 4092, 0, 0, 0, - 12, 16332, 4092, 52, 16368, 0, - 24, 16280, 4088, 108, 16356, 0, - 36, 16236, 4080, 168, 16340, 0, - 44, 16188, 4064, 228, 16324, 0, - 56, 16148, 4052, 292, 16308, 0, - 64, 16108, 4032, 356, 16292, 4, - 72, 16072, 4008, 424, 16276, 4, - 80, 16036, 3980, 492, 16256, 4, - 88, 16004, 3952, 564, 16240, 8, - 96, 15972, 3920, 636, 16220, 8, - 100, 15944, 3884, 712, 16204, 12, - 108, 15916, 3844, 788, 16184, 16, - 112, 15896, 3800, 864, 16164, 20, - 116, 15872, 3756, 944, 16144, 20, - 120, 15852, 3708, 1024, 16124, 24, - 120, 15836, 3656, 1108, 16104, 28, - 124, 15824, 3600, 1192, 16084, 32, - 124, 15808, 3544, 1276, 16064, 36, - 124, 15800, 3484, 1360, 16044, 40, - 128, 15792, 3420, 1448, 16024, 44, - 128, 15784, 3352, 1536, 16004, 48, - 124, 15780, 3288, 1624, 15988, 52, - 124, 15776, 3216, 1712, 15968, 56, - 124, 15776, 3144, 1800, 15948, 64, - 120, 15776, 3068, 1888, 15932, 68, - 120, 15780, 2992, 1976, 15912, 72, - 116, 15784, 2916, 2064, 15896, 76, - 112, 15792, 2836, 2152, 15880, 80, - 108, 15796, 2752, 2244, 15868, 84, - 104, 15804, 2672, 2328, 15852, 88, - 104, 15816, 2588, 2416, 15840, 92, - 100, 15828, 2504, 2504, 15828, 100 }; + 0x0000, 0x0000, 0x1000, 0x0000, 0x0000, 0x0000, + 0x000C, 0x3FD0, 0x0FFC, 0x0034, 0x3FF4, 0x0000, + 0x0018, 0x3F9C, 0x0FF8, 0x006C, 0x3FE8, 0x0000, + 0x0024, 0x3F6C, 0x0FF0, 0x00A8, 0x3FD8, 0x0000, + 0x002C, 0x3F44, 0x0FE4, 0x00E4, 0x3FC8, 0x0000, + 0x0038, 0x3F18, 0x0FD4, 0x0124, 0x3FB8, 0x0000, + 0x0040, 0x3EF0, 0x0FC0, 0x0164, 0x3FA8, 0x0004, + 0x0048, 0x3EC8, 0x0FAC, 0x01A8, 0x3F98, 0x0004, + 0x0050, 0x3EA8, 0x0F94, 0x01EC, 0x3F84, 0x0004, + 0x0058, 0x3E84, 0x0F74, 0x0234, 0x3F74, 0x0008, + 0x0060, 0x3E68, 0x0F54, 0x027C, 0x3F60, 0x0008, + 0x0064, 0x3E4C, 0x0F30, 0x02C8, 0x3F4C, 0x000C, + 0x006C, 0x3E30, 0x0F04, 0x0314, 0x3F3C, 0x0010, + 0x0070, 0x3E18, 0x0EDC, 0x0360, 0x3F28, 0x0014, + 0x0074, 0x3E04, 0x0EB0, 0x03B0, 0x3F14, 0x0014, + 0x0078, 0x3DF0, 0x0E80, 0x0400, 0x3F00, 0x0018, + 0x0078, 0x3DE0, 0x0E4C, 0x0454, 0x3EEC, 0x001C, + 0x007C, 0x3DD0, 0x0E14, 0x04A8, 0x3ED8, 0x0020, + 0x007C, 0x3DC4, 0x0DDC, 0x04FC, 0x3EC4, 0x0024, + 0x007C, 0x3DBC, 0x0DA0, 0x0550, 0x3EB0, 0x0028, + 0x0080, 0x3DB4, 0x0D5C, 0x05A8, 0x3E9C, 0x002C, + 0x0080, 0x3DAC, 0x0D1C, 0x0600, 0x3E88, 0x0030, + 0x007C, 0x3DA8, 0x0CDC, 0x0658, 0x3E74, 0x0034, + 0x007C, 0x3DA4, 0x0C94, 0x06B0, 0x3E64, 0x0038, + 0x007C, 0x3DA4, 0x0C48, 0x0708, 0x3E50, 0x0040, + 0x0078, 0x3DA4, 0x0C00, 0x0760, 0x3E40, 0x0044, + 0x0078, 0x3DA8, 0x0BB4, 0x07B8, 0x3E2C, 0x0048, + 0x0074, 0x3DAC, 0x0B68, 0x0810, 0x3E1C, 0x004C, + 0x0070, 0x3DB4, 0x0B18, 0x0868, 0x3E0C, 0x0050, + 0x006C, 0x3DBC, 0x0AC4, 0x08C4, 0x3DFC, 0x0054, + 0x0068, 0x3DC4, 0x0A74, 0x0918, 0x3DF0, 0x0058, + 0x0068, 0x3DCC, 0x0A20, 0x0970, 0x3DE0, 0x005C, + 0x0064, 0x3DD4, 0x09C8, 0x09C8, 0x3DD4, 0x0064 +}; -static const uint16_t filter_6tap_64p_117[198] = { - 16168, 476, 3568, 476, 16168, 0, - 16180, 428, 3564, 528, 16156, 0, - 16192, 376, 3556, 584, 16144, 4, - 16204, 328, 3548, 636, 16128, 4, - 16216, 280, 3540, 692, 16116, 8, - 16228, 232, 3524, 748, 16104, 12, - 16240, 188, 3512, 808, 16092, 12, - 16252, 148, 3492, 864, 16080, 16, - 16264, 104, 3472, 924, 16068, 16, - 16276, 64, 3452, 984, 16056, 20, - 16284, 28, 3428, 1044, 16048, 24, - 16296, 16376, 3400, 1108, 16036, 24, - 16304, 16340, 3372, 1168, 16024, 28, - 16316, 16304, 3340, 1232, 16016, 32, - 16324, 16272, 3308, 1296, 16004, 32, - 16332, 16244, 3272, 1360, 15996, 36, - 16344, 16212, 3236, 1424, 15988, 36, - 16352, 16188, 3200, 1488, 15980, 40, - 16360, 16160, 3160, 1552, 15972, 40, - 16368, 16136, 3116, 1616, 15964, 40, - 16372, 16112, 3072, 1680, 15956, 44, - 16380, 16092, 3028, 1744, 15952, 44, - 0, 16072, 2980, 1808, 15948, 44, - 8, 16052, 2932, 1872, 15944, 48, - 12, 16036, 2880, 1936, 15940, 48, - 16, 16020, 2828, 2000, 15936, 48, - 20, 16008, 2776, 2064, 15936, 48, - 24, 15996, 2724, 2128, 15936, 48, - 28, 15984, 2668, 2192, 15936, 48, - 32, 15972, 2612, 2252, 15940, 44, - 36, 15964, 2552, 2316, 15940, 44, - 40, 15956, 2496, 2376, 15944, 44, - 40, 15952, 2436, 2436, 15952, 40 }; +//========================================= +// = 6 +// = 64 +// = 1.16666 (input/output) +// = 0 +// = ModifiedLanczos +// = 1.10 +// = 1.12 +//========================================= +static const uint16_t filter_6tap_64p_116[198] = { + 0x3F0C, 0x0240, 0x0D68, 0x0240, 0x3F0C, 0x0000, + 0x3F18, 0x0210, 0x0D64, 0x0274, 0x3F00, 0x0000, + 0x3F24, 0x01E0, 0x0D58, 0x02A8, 0x3EF8, 0x0004, + 0x3F2C, 0x01B0, 0x0D58, 0x02DC, 0x3EEC, 0x0004, + 0x3F38, 0x0180, 0x0D50, 0x0310, 0x3EE0, 0x0008, + 0x3F44, 0x0154, 0x0D40, 0x0348, 0x3ED8, 0x0008, + 0x3F50, 0x0128, 0x0D34, 0x037C, 0x3ECC, 0x000C, + 0x3F5C, 0x00FC, 0x0D20, 0x03B4, 0x3EC4, 0x0010, + 0x3F64, 0x00D4, 0x0D14, 0x03EC, 0x3EB8, 0x0010, + 0x3F70, 0x00AC, 0x0CFC, 0x0424, 0x3EB0, 0x0014, + 0x3F78, 0x0084, 0x0CE8, 0x0460, 0x3EA8, 0x0014, + 0x3F84, 0x0060, 0x0CCC, 0x0498, 0x3EA0, 0x0018, + 0x3F90, 0x003C, 0x0CB4, 0x04D0, 0x3E98, 0x0018, + 0x3F98, 0x0018, 0x0C9C, 0x050C, 0x3E90, 0x0018, + 0x3FA0, 0x3FFC, 0x0C78, 0x0548, 0x3E88, 0x001C, + 0x3FAC, 0x3FDC, 0x0C54, 0x0584, 0x3E84, 0x001C, + 0x3FB4, 0x3FBC, 0x0C3C, 0x05BC, 0x3E7C, 0x001C, + 0x3FBC, 0x3FA0, 0x0C14, 0x05F8, 0x3E78, 0x0020, + 0x3FC4, 0x3F84, 0x0BF0, 0x0634, 0x3E74, 0x0020, + 0x3FCC, 0x3F68, 0x0BCC, 0x0670, 0x3E70, 0x0020, + 0x3FD4, 0x3F50, 0x0BA4, 0x06AC, 0x3E6C, 0x0020, + 0x3FDC, 0x3F38, 0x0B78, 0x06E8, 0x3E6C, 0x0020, + 0x3FE0, 0x3F24, 0x0B50, 0x0724, 0x3E68, 0x0020, + 0x3FE8, 0x3F0C, 0x0B24, 0x0760, 0x3E68, 0x0020, + 0x3FF0, 0x3EFC, 0x0AF4, 0x0798, 0x3E68, 0x0020, + 0x3FF4, 0x3EE8, 0x0AC8, 0x07D4, 0x3E68, 0x0020, + 0x3FFC, 0x3ED8, 0x0A94, 0x0810, 0x3E6C, 0x001C, + 0x0000, 0x3EC8, 0x0A64, 0x0848, 0x3E70, 0x001C, + 0x0000, 0x3EB8, 0x0A38, 0x0880, 0x3E74, 0x001C, + 0x0004, 0x3EAC, 0x0A04, 0x08BC, 0x3E78, 0x0018, + 0x0008, 0x3EA4, 0x09D0, 0x08F4, 0x3E7C, 0x0014, + 0x000C, 0x3E98, 0x0998, 0x092C, 0x3E84, 0x0014, + 0x0010, 0x3E90, 0x0964, 0x0960, 0x3E8C, 0x0010 +}; -static const uint16_t filter_6tap_64p_150[198] = { - 16148, 920, 2724, 920, 16148, 0, - 16152, 880, 2724, 956, 16148, 0, - 16152, 844, 2720, 996, 16144, 0, - 16156, 804, 2716, 1032, 16144, 0, - 16156, 768, 2712, 1072, 16144, 0, - 16160, 732, 2708, 1112, 16144, 16380, - 16164, 696, 2700, 1152, 16144, 16380, - 16168, 660, 2692, 1192, 16148, 16380, - 16172, 628, 2684, 1232, 16148, 16380, - 16176, 592, 2672, 1272, 16152, 16376, - 16180, 560, 2660, 1312, 16152, 16376, - 16184, 524, 2648, 1348, 16156, 16376, - 16192, 492, 2632, 1388, 16160, 16372, - 16196, 460, 2616, 1428, 16164, 16372, - 16200, 432, 2600, 1468, 16168, 16368, - 16204, 400, 2584, 1508, 16176, 16364, - 16212, 368, 2564, 1548, 16180, 16364, - 16216, 340, 2544, 1588, 16188, 16360, - 16220, 312, 2524, 1628, 16196, 16356, - 16228, 284, 2504, 1668, 16204, 16356, - 16232, 256, 2480, 1704, 16212, 16352, - 16240, 232, 2456, 1744, 16224, 16348, - 16244, 204, 2432, 1780, 16232, 16344, - 16248, 180, 2408, 1820, 16244, 16340, - 16256, 156, 2380, 1856, 16256, 16336, - 16260, 132, 2352, 1896, 16268, 16332, - 16268, 108, 2324, 1932, 16280, 16328, - 16272, 88, 2296, 1968, 16292, 16324, - 16276, 64, 2268, 2004, 16308, 16320, - 16284, 44, 2236, 2036, 16324, 16312, - 16288, 24, 2204, 2072, 16340, 16308, - 16292, 8, 2172, 2108, 16356, 16304, - 16300, 16372, 2140, 2140, 16372, 16300 }; +//========================================= +// = 6 +// = 64 +// = 1.49999 (input/output) +// = 0 +// = ModifiedLanczos +// = 1.10 +// = 1.12 +//========================================= +static const uint16_t filter_6tap_64p_149[198] = { + 0x3F14, 0x0394, 0x0AB0, 0x0394, 0x3F14, 0x0000, + 0x3F18, 0x036C, 0x0AB0, 0x03B8, 0x3F14, 0x0000, + 0x3F18, 0x0348, 0x0AAC, 0x03E0, 0x3F14, 0x0000, + 0x3F1C, 0x0320, 0x0AAC, 0x0408, 0x3F10, 0x0000, + 0x3F20, 0x02FC, 0x0AA8, 0x042C, 0x3F10, 0x0000, + 0x3F24, 0x02D8, 0x0AA0, 0x0454, 0x3F10, 0x0000, + 0x3F28, 0x02B4, 0x0A98, 0x047C, 0x3F10, 0x0000, + 0x3F28, 0x0290, 0x0A90, 0x04A4, 0x3F14, 0x0000, + 0x3F30, 0x026C, 0x0A84, 0x04CC, 0x3F14, 0x0000, + 0x3F34, 0x024C, 0x0A7C, 0x04F4, 0x3F14, 0x3FFC, + 0x3F38, 0x0228, 0x0A70, 0x051C, 0x3F18, 0x3FFC, + 0x3F3C, 0x0208, 0x0A64, 0x0544, 0x3F1C, 0x3FF8, + 0x3F40, 0x01E8, 0x0A54, 0x056C, 0x3F20, 0x3FF8, + 0x3F44, 0x01C8, 0x0A48, 0x0594, 0x3F24, 0x3FF4, + 0x3F4C, 0x01A8, 0x0A34, 0x05BC, 0x3F28, 0x3FF4, + 0x3F50, 0x0188, 0x0A28, 0x05E4, 0x3F2C, 0x3FF0, + 0x3F54, 0x016C, 0x0A10, 0x060C, 0x3F34, 0x3FF0, + 0x3F5C, 0x014C, 0x09FC, 0x0634, 0x3F3C, 0x3FEC, + 0x3F60, 0x0130, 0x09EC, 0x065C, 0x3F40, 0x3FE8, + 0x3F68, 0x0114, 0x09D0, 0x0684, 0x3F48, 0x3FE8, + 0x3F6C, 0x00F8, 0x09B8, 0x06AC, 0x3F54, 0x3FE4, + 0x3F74, 0x00E0, 0x09A0, 0x06D0, 0x3F5C, 0x3FE0, + 0x3F78, 0x00C4, 0x098C, 0x06F8, 0x3F64, 0x3FDC, + 0x3F7C, 0x00AC, 0x0970, 0x0720, 0x3F70, 0x3FD8, + 0x3F84, 0x0094, 0x0954, 0x0744, 0x3F7C, 0x3FD4, + 0x3F88, 0x007C, 0x093C, 0x0768, 0x3F88, 0x3FD0, + 0x3F90, 0x0064, 0x091C, 0x0790, 0x3F94, 0x3FCC, + 0x3F94, 0x0050, 0x08FC, 0x07B4, 0x3FA4, 0x3FC8, + 0x3F98, 0x003C, 0x08E0, 0x07D8, 0x3FB0, 0x3FC4, + 0x3FA0, 0x0024, 0x08C0, 0x07FC, 0x3FC0, 0x3FC0, + 0x3FA4, 0x0014, 0x08A4, 0x081C, 0x3FD0, 0x3FB8, + 0x3FAC, 0x0000, 0x0880, 0x0840, 0x3FE0, 0x3FB4, + 0x3FB0, 0x3FF0, 0x0860, 0x0860, 0x3FF0, 0x3FB0 +}; +//========================================= +// = 6 +// = 64 +// = 1.83332 (input/output) +// = 0 +// = ModifiedLanczos +// = 1.10 +// = 1.12 +//========================================= static const uint16_t filter_6tap_64p_183[198] = { - 16296, 1032, 2196, 1032, 16296, 0, - 16292, 1004, 2200, 1060, 16304, 16380, - 16288, 976, 2200, 1088, 16308, 16380, - 16284, 952, 2196, 1116, 16312, 16376, - 16284, 924, 2196, 1144, 16320, 16376, - 16280, 900, 2192, 1172, 16324, 16372, - 16276, 872, 2192, 1200, 16332, 16368, - 16276, 848, 2188, 1228, 16340, 16368, - 16272, 820, 2180, 1256, 16348, 16364, - 16272, 796, 2176, 1280, 16356, 16360, - 16268, 768, 2168, 1308, 16364, 16360, - 16268, 744, 2164, 1336, 16372, 16356, - 16268, 716, 2156, 1364, 16380, 16352, - 16264, 692, 2148, 1392, 4, 16352, - 16264, 668, 2136, 1420, 16, 16348, - 16264, 644, 2128, 1448, 28, 16344, - 16264, 620, 2116, 1472, 36, 16340, - 16264, 596, 2108, 1500, 48, 16340, - 16268, 572, 2096, 1524, 60, 16336, - 16268, 548, 2080, 1552, 72, 16332, - 16268, 524, 2068, 1576, 88, 16328, - 16268, 504, 2056, 1604, 100, 16324, - 16272, 480, 2040, 1628, 112, 16324, - 16272, 456, 2024, 1652, 128, 16320, - 16272, 436, 2008, 1680, 144, 16316, - 16276, 416, 1992, 1704, 156, 16312, - 16276, 392, 1976, 1724, 172, 16308, - 16280, 372, 1956, 1748, 188, 16308, - 16280, 352, 1940, 1772, 204, 16304, - 16284, 332, 1920, 1796, 224, 16300, - 16288, 312, 1900, 1816, 240, 16296, - 16288, 296, 1880, 1840, 256, 16296, - 16292, 276, 1860, 1860, 276, 16292 }; + 0x002C, 0x0420, 0x076C, 0x041C, 0x002C, 0x0000, + 0x0028, 0x040C, 0x0768, 0x0430, 0x0034, 0x0000, + 0x0020, 0x03F8, 0x0768, 0x0448, 0x003C, 0x3FFC, + 0x0018, 0x03E4, 0x0768, 0x045C, 0x0044, 0x3FFC, + 0x0014, 0x03D0, 0x0768, 0x0470, 0x004C, 0x3FF8, + 0x000C, 0x03BC, 0x0764, 0x0484, 0x0058, 0x3FF8, + 0x0008, 0x03A4, 0x0764, 0x049C, 0x0060, 0x3FF4, + 0x0004, 0x0390, 0x0760, 0x04B0, 0x0068, 0x3FF4, + 0x0000, 0x037C, 0x0760, 0x04C4, 0x0070, 0x3FF0, + 0x3FFC, 0x0364, 0x075C, 0x04D8, 0x007C, 0x3FF0, + 0x3FF8, 0x0350, 0x0758, 0x04F0, 0x0084, 0x3FEC, + 0x3FF4, 0x033C, 0x0750, 0x0504, 0x0090, 0x3FEC, + 0x3FF0, 0x0328, 0x074C, 0x0518, 0x009C, 0x3FE8, + 0x3FEC, 0x0314, 0x0744, 0x052C, 0x00A8, 0x3FE8, + 0x3FE8, 0x0304, 0x0740, 0x0540, 0x00B0, 0x3FE4, + 0x3FE4, 0x02EC, 0x073C, 0x0554, 0x00BC, 0x3FE4, + 0x3FE0, 0x02DC, 0x0734, 0x0568, 0x00C8, 0x3FE0, + 0x3FE0, 0x02C4, 0x072C, 0x057C, 0x00D4, 0x3FE0, + 0x3FDC, 0x02B4, 0x0724, 0x058C, 0x00E4, 0x3FDC, + 0x3FDC, 0x02A0, 0x0718, 0x05A0, 0x00F0, 0x3FDC, + 0x3FD8, 0x028C, 0x0714, 0x05B4, 0x00FC, 0x3FD8, + 0x3FD8, 0x0278, 0x0704, 0x05C8, 0x010C, 0x3FD8, + 0x3FD4, 0x0264, 0x0700, 0x05D8, 0x0118, 0x3FD8, + 0x3FD4, 0x0254, 0x06F0, 0x05EC, 0x0128, 0x3FD4, + 0x3FD0, 0x0244, 0x06E8, 0x05FC, 0x0134, 0x3FD4, + 0x3FD0, 0x0230, 0x06DC, 0x060C, 0x0144, 0x3FD4, + 0x3FD0, 0x021C, 0x06D0, 0x0620, 0x0154, 0x3FD0, + 0x3FD0, 0x0208, 0x06C4, 0x0630, 0x0164, 0x3FD0, + 0x3FD0, 0x01F8, 0x06B8, 0x0640, 0x0170, 0x3FD0, + 0x3FCC, 0x01E8, 0x06AC, 0x0650, 0x0180, 0x3FD0, + 0x3FCC, 0x01D8, 0x069C, 0x0660, 0x0190, 0x3FD0, + 0x3FCC, 0x01C4, 0x068C, 0x0670, 0x01A4, 0x3FD0, + 0x3FCC, 0x01B8, 0x0680, 0x067C, 0x01B4, 0x3FCC +}; +//========================================= +// = 7 +// = 64 +// = 0.83333 (input/output) +// = 0 +// = ModifiedLanczos +// = 1.10 +// = 1.12 +//========================================= static const uint16_t filter_7tap_64p_upscale[231] = { - 176, 15760, 2488, 2488, 15760, 176, 0, - 172, 15772, 2404, 2572, 15752, 180, 16380, - 168, 15784, 2324, 2656, 15740, 184, 16380, - 164, 15800, 2240, 2736, 15732, 188, 16376, - 160, 15812, 2152, 2816, 15728, 192, 16376, - 152, 15828, 2068, 2896, 15724, 192, 16376, - 148, 15848, 1984, 2972, 15720, 196, 16372, - 140, 15864, 1896, 3048, 15720, 196, 16372, - 136, 15884, 1812, 3124, 15720, 196, 16368, - 128, 15900, 1724, 3196, 15720, 196, 16368, - 120, 15920, 1640, 3268, 15724, 196, 16368, - 116, 15940, 1552, 3336, 15732, 196, 16364, - 108, 15964, 1468, 3400, 15740, 196, 16364, - 104, 15984, 1384, 3464, 15748, 192, 16364, - 96, 16004, 1300, 3524, 15760, 188, 16364, - 88, 16028, 1216, 3584, 15776, 184, 16364, - 84, 16048, 1132, 3640, 15792, 180, 16360, - 76, 16072, 1048, 3692, 15812, 176, 16360, - 68, 16092, 968, 3744, 15832, 168, 16360, - 64, 16116, 888, 3788, 15856, 160, 16360, - 56, 16140, 812, 3832, 15884, 152, 16360, - 52, 16160, 732, 3876, 15912, 144, 16360, - 44, 16184, 656, 3912, 15944, 136, 16364, - 40, 16204, 584, 3944, 15976, 124, 16364, - 32, 16228, 512, 3976, 16012, 116, 16364, - 28, 16248, 440, 4004, 16048, 104, 16364, - 24, 16268, 372, 4028, 16092, 88, 16368, - 20, 16288, 304, 4048, 16132, 76, 16368, - 12, 16308, 240, 4064, 16180, 60, 16372, - 8, 16328, 176, 4076, 16228, 48, 16372, - 4, 16348, 112, 4088, 16276, 32, 16376, - 0, 16364, 56, 4092, 16328, 16, 16380, - 0, 0, 0, 4096, 0, 0, 0 }; + 0x00B0, 0x3D98, 0x09BC, 0x09B8, 0x3D94, 0x00B0, 0x0000, + 0x00AC, 0x3DA0, 0x0968, 0x0A10, 0x3D88, 0x00B4, 0x0000, + 0x00A8, 0x3DAC, 0x0914, 0x0A60, 0x3D80, 0x00B8, 0x0000, + 0x00A4, 0x3DB8, 0x08C0, 0x0AB4, 0x3D78, 0x00BC, 0x3FFC, + 0x00A0, 0x3DC8, 0x0868, 0x0B00, 0x3D74, 0x00C0, 0x3FFC, + 0x0098, 0x3DD8, 0x0818, 0x0B54, 0x3D6C, 0x00C0, 0x3FF8, + 0x0094, 0x3DE8, 0x07C0, 0x0B9C, 0x3D6C, 0x00C4, 0x3FF8, + 0x008C, 0x3DFC, 0x0768, 0x0BEC, 0x3D68, 0x00C4, 0x3FF8, + 0x0088, 0x3E0C, 0x0714, 0x0C38, 0x3D68, 0x00C4, 0x3FF4, + 0x0080, 0x3E20, 0x06BC, 0x0C80, 0x3D6C, 0x00C4, 0x3FF4, + 0x0078, 0x3E34, 0x0668, 0x0CC4, 0x3D70, 0x00C4, 0x3FF4, + 0x0074, 0x3E48, 0x0610, 0x0D08, 0x3D78, 0x00C4, 0x3FF0, + 0x006C, 0x3E5C, 0x05BC, 0x0D48, 0x3D80, 0x00C4, 0x3FF0, + 0x0068, 0x3E74, 0x0568, 0x0D84, 0x3D88, 0x00C0, 0x3FF0, + 0x0060, 0x3E88, 0x0514, 0x0DC8, 0x3D94, 0x00BC, 0x3FEC, + 0x0058, 0x3E9C, 0x04C0, 0x0E04, 0x3DA4, 0x00B8, 0x3FEC, + 0x0054, 0x3EB4, 0x046C, 0x0E38, 0x3DB4, 0x00B4, 0x3FEC, + 0x004C, 0x3ECC, 0x0418, 0x0E6C, 0x3DC8, 0x00B0, 0x3FEC, + 0x0044, 0x3EE0, 0x03C8, 0x0EA4, 0x3DDC, 0x00A8, 0x3FEC, + 0x0040, 0x3EF8, 0x0378, 0x0ED0, 0x3DF4, 0x00A0, 0x3FEC, + 0x0038, 0x3F0C, 0x032C, 0x0EFC, 0x3E10, 0x0098, 0x3FEC, + 0x0034, 0x3F24, 0x02DC, 0x0F24, 0x3E2C, 0x0090, 0x3FEC, + 0x002C, 0x3F38, 0x0294, 0x0F4C, 0x3E48, 0x0088, 0x3FEC, + 0x0028, 0x3F50, 0x0248, 0x0F68, 0x3E6C, 0x007C, 0x3FF0, + 0x0020, 0x3F64, 0x0200, 0x0F88, 0x3E90, 0x0074, 0x3FF0, + 0x001C, 0x3F7C, 0x01B8, 0x0FA4, 0x3EB4, 0x0068, 0x3FF0, + 0x0018, 0x3F90, 0x0174, 0x0FBC, 0x3EDC, 0x0058, 0x3FF4, + 0x0014, 0x3FA4, 0x0130, 0x0FD0, 0x3F08, 0x004C, 0x3FF4, + 0x000C, 0x3FB8, 0x00F0, 0x0FE4, 0x3F34, 0x003C, 0x3FF8, + 0x0008, 0x3FCC, 0x00B0, 0x0FF0, 0x3F64, 0x0030, 0x3FF8, + 0x0004, 0x3FDC, 0x0070, 0x0FFC, 0x3F98, 0x0020, 0x3FFC, + 0x0000, 0x3FF0, 0x0038, 0x0FFC, 0x3FCC, 0x0010, 0x0000, + 0x0000, 0x0000, 0x0000, 0x1000, 0x0000, 0x0000, 0x0000 +}; -static const uint16_t filter_7tap_64p_117[231] = { - 92, 15868, 2464, 2464, 15868, 92, 0, - 96, 15864, 2404, 2528, 15876, 88, 0, - 100, 15860, 2344, 2584, 15884, 84, 0, - 104, 15856, 2280, 2644, 15892, 76, 0, - 108, 15852, 2216, 2700, 15904, 72, 0, - 108, 15852, 2152, 2756, 15916, 64, 0, - 112, 15852, 2088, 2812, 15932, 60, 0, - 112, 15852, 2024, 2864, 15948, 52, 0, - 112, 15856, 1960, 2916, 15964, 44, 0, - 116, 15860, 1892, 2964, 15984, 36, 0, - 116, 15864, 1828, 3016, 16004, 24, 4, - 116, 15868, 1760, 3060, 16024, 16, 4, - 116, 15876, 1696, 3108, 16048, 8, 8, - 116, 15884, 1628, 3152, 16072, 16380, 8, - 112, 15892, 1564, 3192, 16100, 16372, 8, - 112, 15900, 1496, 3232, 16124, 16360, 12, - 112, 15908, 1428, 3268, 16156, 16348, 12, - 108, 15920, 1364, 3304, 16188, 16336, 16, - 108, 15928, 1300, 3340, 16220, 16324, 20, - 104, 15940, 1232, 3372, 16252, 16312, 20, - 104, 15952, 1168, 3400, 16288, 16300, 24, - 100, 15964, 1104, 3428, 16328, 16284, 28, - 96, 15980, 1040, 3452, 16364, 16272, 28, - 96, 15992, 976, 3476, 20, 16256, 32, - 92, 16004, 916, 3496, 64, 16244, 36, - 88, 16020, 856, 3516, 108, 16228, 40, - 84, 16032, 792, 3532, 152, 16216, 44, - 80, 16048, 732, 3544, 200, 16200, 48, - 80, 16064, 676, 3556, 248, 16184, 48, - 76, 16080, 616, 3564, 296, 16168, 52, - 72, 16092, 560, 3568, 344, 16156, 56, - 68, 16108, 504, 3572, 396, 16140, 60, - 64, 16124, 452, 3576, 452, 16124, 64 }; +//========================================= +// = 7 +// = 64 +// = 1.16666 (input/output) +// = 0 +// = ModifiedLanczos +// = 1.10 +// = 1.12 +//========================================= +static const uint16_t filter_7tap_64p_116[231] = { + 0x0020, 0x3E58, 0x0988, 0x0988, 0x3E58, 0x0020, 0x0000, + 0x0024, 0x3E4C, 0x0954, 0x09C0, 0x3E64, 0x0018, 0x0000, + 0x002C, 0x3E44, 0x091C, 0x09F4, 0x3E70, 0x0010, 0x0000, + 0x0030, 0x3E3C, 0x08E8, 0x0A24, 0x3E80, 0x0008, 0x0000, + 0x0034, 0x3E34, 0x08AC, 0x0A5C, 0x3E90, 0x0000, 0x0000, + 0x003C, 0x3E30, 0x0870, 0x0A84, 0x3EA0, 0x3FFC, 0x0004, + 0x0040, 0x3E28, 0x0838, 0x0AB4, 0x3EB4, 0x3FF4, 0x0004, + 0x0044, 0x3E24, 0x07FC, 0x0AE4, 0x3EC8, 0x3FEC, 0x0004, + 0x0048, 0x3E24, 0x07C4, 0x0B08, 0x3EDC, 0x3FE4, 0x0008, + 0x0048, 0x3E20, 0x0788, 0x0B3C, 0x3EF4, 0x3FD8, 0x0008, + 0x004C, 0x3E20, 0x074C, 0x0B60, 0x3F0C, 0x3FD0, 0x000C, + 0x0050, 0x3E20, 0x0710, 0x0B8C, 0x3F24, 0x3FC4, 0x000C, + 0x0050, 0x3E20, 0x06D4, 0x0BB0, 0x3F40, 0x3FBC, 0x0010, + 0x0054, 0x3E24, 0x0698, 0x0BD4, 0x3F5C, 0x3FB0, 0x0010, + 0x0054, 0x3E24, 0x065C, 0x0BFC, 0x3F78, 0x3FA4, 0x0014, + 0x0054, 0x3E28, 0x0624, 0x0C1C, 0x3F98, 0x3F98, 0x0014, + 0x0058, 0x3E2C, 0x05E4, 0x0C3C, 0x3FB8, 0x3F8C, 0x0018, + 0x0058, 0x3E34, 0x05A8, 0x0C58, 0x3FD8, 0x3F80, 0x001C, + 0x0058, 0x3E38, 0x0570, 0x0C78, 0x3FF8, 0x3F74, 0x001C, + 0x0058, 0x3E40, 0x0534, 0x0C94, 0x0018, 0x3F68, 0x0020, + 0x0058, 0x3E48, 0x04F4, 0x0CAC, 0x0040, 0x3F5C, 0x0024, + 0x0058, 0x3E50, 0x04BC, 0x0CC4, 0x0064, 0x3F50, 0x0024, + 0x0054, 0x3E58, 0x0484, 0x0CD8, 0x008C, 0x3F44, 0x0028, + 0x0054, 0x3E60, 0x0448, 0x0CEC, 0x00B4, 0x3F38, 0x002C, + 0x0054, 0x3E68, 0x0410, 0x0CFC, 0x00E0, 0x3F28, 0x0030, + 0x0054, 0x3E74, 0x03D4, 0x0D0C, 0x010C, 0x3F1C, 0x0030, + 0x0050, 0x3E7C, 0x03A0, 0x0D18, 0x0138, 0x3F10, 0x0034, + 0x0050, 0x3E88, 0x0364, 0x0D24, 0x0164, 0x3F04, 0x0038, + 0x004C, 0x3E94, 0x0330, 0x0D30, 0x0194, 0x3EF4, 0x0038, + 0x004C, 0x3EA0, 0x02F8, 0x0D34, 0x01C4, 0x3EE8, 0x003C, + 0x0048, 0x3EAC, 0x02C0, 0x0D3C, 0x01F4, 0x3EDC, 0x0040, + 0x0048, 0x3EB8, 0x0290, 0x0D3C, 0x0224, 0x3ED0, 0x0040, + 0x0044, 0x3EC4, 0x0258, 0x0D40, 0x0258, 0x3EC4, 0x0044 +}; -static const uint16_t filter_7tap_64p_150[231] = { - 16224, 16380, 2208, 2208, 16380, 16224, 0, - 16232, 16360, 2172, 2236, 16, 16216, 0, - 16236, 16340, 2140, 2268, 40, 16212, 0, - 16244, 16324, 2104, 2296, 60, 16204, 4, - 16252, 16304, 2072, 2324, 84, 16196, 4, - 16256, 16288, 2036, 2352, 108, 16192, 4, - 16264, 16268, 2000, 2380, 132, 16184, 8, - 16272, 16252, 1960, 2408, 160, 16176, 8, - 16276, 16240, 1924, 2432, 184, 16172, 8, - 16284, 16224, 1888, 2456, 212, 16164, 8, - 16288, 16212, 1848, 2480, 240, 16160, 12, - 16296, 16196, 1812, 2500, 268, 16152, 12, - 16300, 16184, 1772, 2524, 296, 16144, 12, - 16308, 16172, 1736, 2544, 324, 16140, 12, - 16312, 16164, 1696, 2564, 356, 16136, 12, - 16320, 16152, 1656, 2584, 388, 16128, 12, - 16324, 16144, 1616, 2600, 416, 16124, 12, - 16328, 16136, 1576, 2616, 448, 16116, 12, - 16332, 16128, 1536, 2632, 480, 16112, 12, - 16340, 16120, 1496, 2648, 516, 16108, 12, - 16344, 16112, 1456, 2660, 548, 16104, 12, - 16348, 16104, 1416, 2672, 580, 16100, 12, - 16352, 16100, 1376, 2684, 616, 16096, 12, - 16356, 16096, 1336, 2696, 652, 16092, 12, - 16360, 16092, 1296, 2704, 688, 16088, 12, - 16364, 16088, 1256, 2712, 720, 16084, 12, - 16368, 16084, 1220, 2720, 760, 16084, 8, - 16368, 16080, 1180, 2724, 796, 16080, 8, - 16372, 16080, 1140, 2732, 832, 16080, 8, - 16376, 16076, 1100, 2732, 868, 16076, 4, - 16380, 16076, 1060, 2736, 908, 16076, 4, - 16380, 16076, 1020, 2740, 944, 16076, 0, - 0, 16076, 984, 2740, 984, 16076, 0 }; +//========================================= +// = 7 +// = 64 +// = 1.49999 (input/output) +// = 0 +// = ModifiedLanczos +// = 1.10 +// = 1.12 +//========================================= +static const uint16_t filter_7tap_64p_149[231] = { + 0x3F68, 0x3FEC, 0x08A8, 0x08AC, 0x3FF0, 0x3F68, 0x0000, + 0x3F70, 0x3FDC, 0x0888, 0x08CC, 0x0000, 0x3F60, 0x0000, + 0x3F74, 0x3FC8, 0x0868, 0x08F0, 0x0014, 0x3F58, 0x0000, + 0x3F7C, 0x3FB4, 0x0844, 0x0908, 0x002C, 0x3F54, 0x0004, + 0x3F84, 0x3FA4, 0x0820, 0x0924, 0x0044, 0x3F4C, 0x0004, + 0x3F88, 0x3F90, 0x0800, 0x0944, 0x005C, 0x3F44, 0x0004, + 0x3F90, 0x3F80, 0x07D8, 0x095C, 0x0074, 0x3F40, 0x0008, + 0x3F98, 0x3F70, 0x07B0, 0x097C, 0x008C, 0x3F38, 0x0008, + 0x3F9C, 0x3F60, 0x0790, 0x0994, 0x00A8, 0x3F30, 0x0008, + 0x3FA4, 0x3F54, 0x0764, 0x09B0, 0x00C4, 0x3F28, 0x0008, + 0x3FA8, 0x3F48, 0x0740, 0x09C4, 0x00DC, 0x3F24, 0x000C, + 0x3FB0, 0x3F38, 0x0718, 0x09DC, 0x00FC, 0x3F1C, 0x000C, + 0x3FB4, 0x3F2C, 0x06F0, 0x09F4, 0x0118, 0x3F18, 0x000C, + 0x3FBC, 0x3F24, 0x06C8, 0x0A08, 0x0134, 0x3F10, 0x000C, + 0x3FC0, 0x3F18, 0x06A0, 0x0A1C, 0x0154, 0x3F08, 0x0010, + 0x3FC8, 0x3F10, 0x0678, 0x0A2C, 0x0170, 0x3F04, 0x0010, + 0x3FCC, 0x3F04, 0x0650, 0x0A40, 0x0190, 0x3F00, 0x0010, + 0x3FD0, 0x3EFC, 0x0628, 0x0A54, 0x01B0, 0x3EF8, 0x0010, + 0x3FD4, 0x3EF4, 0x0600, 0x0A64, 0x01D0, 0x3EF4, 0x0010, + 0x3FDC, 0x3EEC, 0x05D8, 0x0A6C, 0x01F4, 0x3EF0, 0x0010, + 0x3FE0, 0x3EE8, 0x05B0, 0x0A7C, 0x0214, 0x3EE8, 0x0010, + 0x3FE4, 0x3EE0, 0x0588, 0x0A88, 0x0238, 0x3EE4, 0x0010, + 0x3FE8, 0x3EDC, 0x055C, 0x0A98, 0x0258, 0x3EE0, 0x0010, + 0x3FEC, 0x3ED8, 0x0534, 0x0AA0, 0x027C, 0x3EDC, 0x0010, + 0x3FF0, 0x3ED4, 0x050C, 0x0AAC, 0x02A0, 0x3ED8, 0x000C, + 0x3FF4, 0x3ED0, 0x04E4, 0x0AB4, 0x02C4, 0x3ED4, 0x000C, + 0x3FF4, 0x3ECC, 0x04C0, 0x0ABC, 0x02E8, 0x3ED0, 0x000C, + 0x3FF8, 0x3ECC, 0x0494, 0x0AC0, 0x030C, 0x3ED0, 0x000C, + 0x3FFC, 0x3EC8, 0x046C, 0x0AC8, 0x0334, 0x3ECC, 0x0008, + 0x0000, 0x3EC8, 0x0444, 0x0AC8, 0x0358, 0x3ECC, 0x0008, + 0x0000, 0x3EC8, 0x041C, 0x0ACC, 0x0380, 0x3EC8, 0x0008, + 0x0000, 0x3EC8, 0x03F4, 0x0AD0, 0x03A8, 0x3EC8, 0x0004, + 0x0004, 0x3EC8, 0x03CC, 0x0AD0, 0x03CC, 0x3EC8, 0x0004 +}; +//========================================= +// = 7 +// = 64 +// = 1.83332 (input/output) +// = 0 +// = ModifiedLanczos +// = 1.10 +// = 1.12 +//========================================= static const uint16_t filter_7tap_64p_183[231] = { - 16216, 324, 1884, 1884, 324, 16216, 0, - 16220, 304, 1864, 1904, 344, 16216, 0, - 16224, 284, 1844, 1924, 364, 16216, 0, - 16224, 264, 1824, 1944, 384, 16212, 16380, - 16228, 248, 1804, 1960, 408, 16212, 16380, - 16228, 228, 1784, 1976, 428, 16208, 16380, - 16232, 212, 1760, 1996, 452, 16208, 16380, - 16236, 192, 1740, 2012, 472, 16208, 16376, - 16240, 176, 1716, 2028, 496, 16208, 16376, - 16240, 160, 1696, 2040, 516, 16208, 16376, - 16244, 144, 1672, 2056, 540, 16208, 16376, - 16248, 128, 1648, 2068, 564, 16208, 16372, - 16252, 112, 1624, 2084, 588, 16208, 16372, - 16256, 96, 1600, 2096, 612, 16208, 16368, - 16256, 84, 1576, 2108, 636, 16208, 16368, - 16260, 68, 1552, 2120, 660, 16208, 16368, - 16264, 56, 1524, 2132, 684, 16212, 16364, - 16268, 40, 1500, 2140, 712, 16212, 16364, - 16272, 28, 1476, 2152, 736, 16216, 16360, - 16276, 16, 1448, 2160, 760, 16216, 16356, - 16280, 4, 1424, 2168, 788, 16220, 16356, - 16284, 16376, 1396, 2176, 812, 16224, 16352, - 16288, 16368, 1372, 2184, 840, 16224, 16352, - 16292, 16356, 1344, 2188, 864, 16228, 16348, - 16292, 16344, 1320, 2196, 892, 16232, 16344, - 16296, 16336, 1292, 2200, 916, 16236, 16344, - 16300, 16324, 1264, 2204, 944, 16240, 16340, - 16304, 16316, 1240, 2208, 972, 16248, 16336, - 16308, 16308, 1212, 2212, 996, 16252, 16332, - 16312, 16300, 1184, 2216, 1024, 16256, 16332, - 16316, 16292, 1160, 2216, 1052, 16264, 16328, - 16316, 16284, 1132, 2216, 1076, 16268, 16324, - 16320, 16276, 1104, 2216, 1104, 16276, 16320 }; + 0x3FA4, 0x01E8, 0x0674, 0x0674, 0x01E8, 0x3FA4, 0x0000, + 0x3FA4, 0x01D4, 0x0668, 0x0684, 0x01F8, 0x3FA4, 0x0000, + 0x3FA4, 0x01C4, 0x0658, 0x0690, 0x0208, 0x3FA8, 0x0000, + 0x3FA0, 0x01B4, 0x064C, 0x06A0, 0x021C, 0x3FA8, 0x3FFC, + 0x3FA0, 0x01A4, 0x063C, 0x06AC, 0x022C, 0x3FAC, 0x3FFC, + 0x3FA0, 0x0194, 0x0630, 0x06B4, 0x0240, 0x3FAC, 0x3FFC, + 0x3FA0, 0x0184, 0x0620, 0x06C4, 0x0250, 0x3FB0, 0x3FF8, + 0x3FA0, 0x0174, 0x0614, 0x06CC, 0x0264, 0x3FB0, 0x3FF8, + 0x3FA0, 0x0164, 0x0604, 0x06D8, 0x0278, 0x3FB4, 0x3FF4, + 0x3FA0, 0x0154, 0x05F4, 0x06E4, 0x0288, 0x3FB8, 0x3FF4, + 0x3FA0, 0x0148, 0x05E4, 0x06EC, 0x029C, 0x3FBC, 0x3FF0, + 0x3FA0, 0x0138, 0x05D4, 0x06F4, 0x02B0, 0x3FC0, 0x3FF0, + 0x3FA0, 0x0128, 0x05C4, 0x0704, 0x02C4, 0x3FC0, 0x3FEC, + 0x3FA0, 0x011C, 0x05B4, 0x0708, 0x02D8, 0x3FC4, 0x3FEC, + 0x3FA4, 0x010C, 0x05A4, 0x0714, 0x02E8, 0x3FC8, 0x3FE8, + 0x3FA4, 0x0100, 0x0590, 0x0718, 0x02FC, 0x3FD0, 0x3FE8, + 0x3FA4, 0x00F0, 0x0580, 0x0724, 0x0310, 0x3FD4, 0x3FE4, + 0x3FA4, 0x00E4, 0x056C, 0x072C, 0x0324, 0x3FD8, 0x3FE4, + 0x3FA8, 0x00D8, 0x055C, 0x0730, 0x0338, 0x3FDC, 0x3FE0, + 0x3FA8, 0x00CC, 0x0548, 0x0738, 0x034C, 0x3FE4, 0x3FDC, + 0x3FA8, 0x00BC, 0x0538, 0x0740, 0x0360, 0x3FE8, 0x3FDC, + 0x3FAC, 0x00B0, 0x0528, 0x0744, 0x0374, 0x3FEC, 0x3FD8, + 0x3FAC, 0x00A4, 0x0514, 0x0748, 0x0388, 0x3FF4, 0x3FD8, + 0x3FB0, 0x0098, 0x0500, 0x074C, 0x039C, 0x3FFC, 0x3FD4, + 0x3FB0, 0x0090, 0x04EC, 0x0750, 0x03B0, 0x0000, 0x3FD4, + 0x3FB0, 0x0084, 0x04DC, 0x0758, 0x03C4, 0x0004, 0x3FD0, + 0x3FB4, 0x0078, 0x04CC, 0x0758, 0x03D8, 0x000C, 0x3FCC, + 0x3FB4, 0x006C, 0x04B8, 0x075C, 0x03EC, 0x0014, 0x3FCC, + 0x3FB8, 0x0064, 0x04A0, 0x0760, 0x0400, 0x001C, 0x3FC8, + 0x3FB8, 0x0058, 0x0490, 0x0760, 0x0414, 0x0024, 0x3FC8, + 0x3FBC, 0x0050, 0x047C, 0x0760, 0x0428, 0x002C, 0x3FC4, + 0x3FBC, 0x0048, 0x0464, 0x0764, 0x043C, 0x0034, 0x3FC4, + 0x3FC0, 0x003C, 0x0454, 0x0764, 0x0450, 0x003C, 0x3FC0 +}; +//========================================= +// = 8 +// = 64 +// = 0.83333 (input/output) +// = 0 +// = ModifiedLanczos +// = 1.10 +// = 1.12 +//========================================= static const uint16_t filter_8tap_64p_upscale[264] = { - 0, 0, 0, 4096, 0, 0, 0, 0, - 16376, 20, 16328, 4092, 56, 16364, 4, 0, - 16372, 36, 16272, 4088, 116, 16340, 12, 0, - 16364, 56, 16220, 4080, 180, 16320, 20, 0, - 16360, 76, 16172, 4064, 244, 16296, 24, 16380, - 16356, 92, 16124, 4048, 312, 16276, 32, 16380, - 16352, 108, 16080, 4032, 380, 16252, 40, 16380, - 16344, 124, 16036, 4008, 452, 16228, 48, 16380, - 16340, 136, 15996, 3980, 524, 16204, 56, 16380, - 16340, 152, 15956, 3952, 600, 16180, 64, 16376, - 16336, 164, 15920, 3920, 672, 16156, 76, 16376, - 16332, 176, 15888, 3884, 752, 16132, 84, 16376, - 16328, 188, 15860, 3844, 828, 16104, 92, 16372, - 16328, 200, 15828, 3800, 908, 16080, 100, 16372, - 16324, 208, 15804, 3756, 992, 16056, 108, 16372, - 16324, 216, 15780, 3708, 1072, 16032, 120, 16368, - 16320, 224, 15760, 3656, 1156, 16008, 128, 16368, - 16320, 232, 15740, 3604, 1240, 15984, 136, 16364, - 16320, 240, 15724, 3548, 1324, 15960, 144, 16364, - 16320, 244, 15708, 3488, 1412, 15936, 152, 16360, - 16320, 248, 15696, 3428, 1496, 15912, 160, 16360, - 16320, 252, 15688, 3364, 1584, 15892, 172, 16356, - 16320, 256, 15680, 3296, 1672, 15868, 180, 16352, - 16320, 256, 15672, 3228, 1756, 15848, 188, 16352, - 16320, 256, 15668, 3156, 1844, 15828, 192, 16348, - 16320, 260, 15668, 3084, 1932, 15808, 200, 16348, - 16320, 256, 15668, 3012, 2020, 15792, 208, 16344, - 16324, 256, 15668, 2936, 2108, 15772, 216, 16344, - 16324, 256, 15672, 2856, 2192, 15756, 220, 16340, - 16324, 252, 15676, 2776, 2280, 15740, 228, 16336, - 16328, 252, 15684, 2696, 2364, 15728, 232, 16336, - 16328, 248, 15692, 2616, 2448, 15716, 240, 16332, - 16332, 244, 15704, 2532, 2532, 15704, 244, 16332 }; + 0x0000, 0x0000, 0x0000, 0x1000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x3FFC, 0x0014, 0x3FC8, 0x1000, 0x0038, 0x3FEC, 0x0004, 0x0000, + 0x3FF4, 0x0024, 0x3F94, 0x0FFC, 0x0074, 0x3FD8, 0x000C, 0x0000, + 0x3FF0, 0x0038, 0x3F60, 0x0FEC, 0x00B4, 0x3FC4, 0x0014, 0x0000, + 0x3FEC, 0x004C, 0x3F2C, 0x0FE4, 0x00F4, 0x3FAC, 0x0018, 0x0000, + 0x3FE4, 0x005C, 0x3F00, 0x0FD4, 0x0138, 0x3F94, 0x0020, 0x0000, + 0x3FE0, 0x006C, 0x3ED0, 0x0FC4, 0x017C, 0x3F7C, 0x0028, 0x0000, + 0x3FDC, 0x007C, 0x3EA8, 0x0FA4, 0x01C4, 0x3F68, 0x0030, 0x0000, + 0x3FD8, 0x0088, 0x3E80, 0x0F90, 0x020C, 0x3F50, 0x0038, 0x3FFC, + 0x3FD4, 0x0098, 0x3E58, 0x0F70, 0x0258, 0x3F38, 0x0040, 0x3FFC, + 0x3FD0, 0x00A4, 0x3E34, 0x0F54, 0x02A0, 0x3F1C, 0x004C, 0x3FFC, + 0x3FD0, 0x00B0, 0x3E14, 0x0F28, 0x02F0, 0x3F04, 0x0054, 0x3FFC, + 0x3FCC, 0x00BC, 0x3DF4, 0x0F08, 0x033C, 0x3EEC, 0x005C, 0x3FF8, + 0x3FC8, 0x00C8, 0x3DD8, 0x0EDC, 0x038C, 0x3ED4, 0x0064, 0x3FF8, + 0x3FC8, 0x00D0, 0x3DC0, 0x0EAC, 0x03E0, 0x3EBC, 0x006C, 0x3FF4, + 0x3FC4, 0x00D8, 0x3DA8, 0x0E7C, 0x0430, 0x3EA4, 0x0078, 0x3FF4, + 0x3FC4, 0x00E0, 0x3D94, 0x0E48, 0x0484, 0x3E8C, 0x0080, 0x3FF0, + 0x3FC4, 0x00E8, 0x3D80, 0x0E10, 0x04D8, 0x3E74, 0x0088, 0x3FF0, + 0x3FC4, 0x00F0, 0x3D70, 0x0DD8, 0x052C, 0x3E5C, 0x0090, 0x3FEC, + 0x3FC0, 0x00F4, 0x3D60, 0x0DA0, 0x0584, 0x3E44, 0x0098, 0x3FEC, + 0x3FC0, 0x00F8, 0x3D54, 0x0D68, 0x05D8, 0x3E2C, 0x00A0, 0x3FE8, + 0x3FC0, 0x00FC, 0x3D48, 0x0D20, 0x0630, 0x3E18, 0x00AC, 0x3FE8, + 0x3FC0, 0x0100, 0x3D40, 0x0CE0, 0x0688, 0x3E00, 0x00B4, 0x3FE4, + 0x3FC4, 0x0100, 0x3D3C, 0x0C98, 0x06DC, 0x3DEC, 0x00BC, 0x3FE4, + 0x3FC4, 0x0100, 0x3D38, 0x0C58, 0x0734, 0x3DD8, 0x00C0, 0x3FE0, + 0x3FC4, 0x0104, 0x3D38, 0x0C0C, 0x078C, 0x3DC4, 0x00C8, 0x3FDC, + 0x3FC4, 0x0100, 0x3D38, 0x0BC4, 0x07E4, 0x3DB0, 0x00D0, 0x3FDC, + 0x3FC4, 0x0100, 0x3D38, 0x0B78, 0x083C, 0x3DA0, 0x00D8, 0x3FD8, + 0x3FC8, 0x0100, 0x3D3C, 0x0B28, 0x0890, 0x3D90, 0x00DC, 0x3FD8, + 0x3FC8, 0x00FC, 0x3D40, 0x0ADC, 0x08E8, 0x3D80, 0x00E4, 0x3FD4, + 0x3FCC, 0x00FC, 0x3D48, 0x0A84, 0x093C, 0x3D74, 0x00E8, 0x3FD4, + 0x3FCC, 0x00F8, 0x3D50, 0x0A38, 0x0990, 0x3D64, 0x00F0, 0x3FD0, + 0x3FD0, 0x00F4, 0x3D58, 0x09E0, 0x09E4, 0x3D5C, 0x00F4, 0x3FD0 +}; -static const uint16_t filter_8tap_64p_117[264] = { - 116, 16100, 428, 3564, 428, 16100, 116, 0, - 112, 16116, 376, 3564, 484, 16084, 120, 16380, - 104, 16136, 324, 3560, 540, 16064, 124, 16380, - 100, 16152, 272, 3556, 600, 16048, 128, 16380, - 96, 16168, 220, 3548, 656, 16032, 136, 16376, - 88, 16188, 172, 3540, 716, 16016, 140, 16376, - 84, 16204, 124, 3528, 780, 16000, 144, 16376, - 80, 16220, 76, 3512, 840, 15984, 148, 16372, - 76, 16236, 32, 3496, 904, 15968, 152, 16372, - 68, 16252, 16376, 3480, 968, 15952, 156, 16372, - 64, 16268, 16332, 3456, 1032, 15936, 160, 16372, - 60, 16284, 16292, 3432, 1096, 15920, 164, 16368, - 56, 16300, 16252, 3408, 1164, 15908, 164, 16368, - 48, 16316, 16216, 3380, 1228, 15892, 168, 16368, - 44, 16332, 16180, 3348, 1296, 15880, 168, 16368, - 40, 16348, 16148, 3316, 1364, 15868, 172, 16364, - 36, 16360, 16116, 3284, 1428, 15856, 172, 16364, - 32, 16376, 16084, 3248, 1496, 15848, 176, 16364, - 28, 4, 16052, 3208, 1564, 15836, 176, 16364, - 24, 16, 16028, 3168, 1632, 15828, 176, 16364, - 20, 28, 16000, 3124, 1700, 15820, 176, 16364, - 16, 40, 15976, 3080, 1768, 15812, 176, 16364, - 12, 52, 15952, 3036, 1836, 15808, 176, 16364, - 8, 64, 15932, 2988, 1904, 15800, 176, 16364, - 4, 76, 15912, 2940, 1972, 15800, 172, 16364, - 4, 84, 15892, 2888, 2040, 15796, 172, 16364, - 0, 96, 15876, 2836, 2104, 15792, 168, 16364, - 16380, 104, 15864, 2780, 2172, 15792, 164, 16364, - 16380, 112, 15848, 2724, 2236, 15792, 160, 16364, - 16376, 120, 15836, 2668, 2300, 15796, 156, 16368, - 16376, 128, 15828, 2608, 2364, 15800, 152, 16368, - 16372, 136, 15816, 2548, 2428, 15804, 148, 16368, - 16372, 140, 15812, 2488, 2488, 15812, 140, 16372 }; +//========================================= +// = 8 +// = 64 +// = 1.16666 (input/output) +// = 0 +// = ModifiedLanczos +// = 1.10 +// = 1.12 +//========================================= +static const uint16_t filter_8tap_64p_116[264] = { + 0x0080, 0x3E90, 0x0268, 0x0D14, 0x0264, 0x3E90, 0x0080, 0x0000, + 0x007C, 0x3E9C, 0x0238, 0x0D14, 0x0298, 0x3E84, 0x0080, 0x0000, + 0x0078, 0x3EAC, 0x0200, 0x0D10, 0x02D0, 0x3E78, 0x0084, 0x0000, + 0x0078, 0x3EB8, 0x01D0, 0x0D0C, 0x0304, 0x3E6C, 0x0084, 0x0000, + 0x0074, 0x3EC8, 0x01A0, 0x0D00, 0x033C, 0x3E60, 0x0088, 0x0000, + 0x0070, 0x3ED4, 0x0170, 0x0D00, 0x0374, 0x3E54, 0x0088, 0x3FFC, + 0x006C, 0x3EE4, 0x0140, 0x0CF8, 0x03AC, 0x3E48, 0x0088, 0x3FFC, + 0x006C, 0x3EF0, 0x0114, 0x0CE8, 0x03E4, 0x3E3C, 0x008C, 0x3FFC, + 0x0068, 0x3F00, 0x00E8, 0x0CD8, 0x041C, 0x3E34, 0x008C, 0x3FFC, + 0x0064, 0x3F10, 0x00BC, 0x0CCC, 0x0454, 0x3E28, 0x008C, 0x3FFC, + 0x0060, 0x3F1C, 0x0090, 0x0CBC, 0x0490, 0x3E20, 0x008C, 0x3FFC, + 0x005C, 0x3F2C, 0x0068, 0x0CA4, 0x04CC, 0x3E18, 0x008C, 0x3FFC, + 0x0058, 0x3F38, 0x0040, 0x0C94, 0x0504, 0x3E10, 0x008C, 0x3FFC, + 0x0054, 0x3F48, 0x001C, 0x0C7C, 0x0540, 0x3E08, 0x0088, 0x3FFC, + 0x0050, 0x3F54, 0x3FF8, 0x0C60, 0x057C, 0x3E04, 0x0088, 0x3FFC, + 0x004C, 0x3F64, 0x3FD4, 0x0C44, 0x05B8, 0x3DFC, 0x0088, 0x3FFC, + 0x0048, 0x3F70, 0x3FB4, 0x0C28, 0x05F4, 0x3DF8, 0x0084, 0x3FFC, + 0x0044, 0x3F80, 0x3F90, 0x0C0C, 0x0630, 0x3DF4, 0x0080, 0x3FFC, + 0x0040, 0x3F8C, 0x3F70, 0x0BE8, 0x066C, 0x3DF4, 0x0080, 0x3FFC, + 0x003C, 0x3F9C, 0x3F50, 0x0BC8, 0x06A8, 0x3DF0, 0x007C, 0x3FFC, + 0x0038, 0x3FA8, 0x3F34, 0x0BA0, 0x06E4, 0x3DF0, 0x0078, 0x0000, + 0x0034, 0x3FB4, 0x3F18, 0x0B80, 0x071C, 0x3DF0, 0x0074, 0x0000, + 0x0030, 0x3FC0, 0x3EFC, 0x0B5C, 0x0758, 0x3DF0, 0x0070, 0x0000, + 0x002C, 0x3FCC, 0x3EE4, 0x0B34, 0x0794, 0x3DF4, 0x0068, 0x0000, + 0x002C, 0x3FDC, 0x3ECC, 0x0B08, 0x07CC, 0x3DF4, 0x0064, 0x0000, + 0x0028, 0x3FE4, 0x3EB4, 0x0AE0, 0x0808, 0x3DF8, 0x0060, 0x0000, + 0x0024, 0x3FF0, 0x3EA0, 0x0AB0, 0x0840, 0x3E00, 0x0058, 0x0004, + 0x0020, 0x3FFC, 0x3E90, 0x0A84, 0x0878, 0x3E04, 0x0050, 0x0004, + 0x001C, 0x0004, 0x3E7C, 0x0A54, 0x08B0, 0x3E0C, 0x004C, 0x0008, + 0x0018, 0x000C, 0x3E68, 0x0A28, 0x08E8, 0x3E18, 0x0044, 0x0008, + 0x0018, 0x0018, 0x3E54, 0x09F4, 0x0920, 0x3E20, 0x003C, 0x000C, + 0x0014, 0x0020, 0x3E48, 0x09C0, 0x0954, 0x3E2C, 0x0034, 0x0010, + 0x0010, 0x002C, 0x3E3C, 0x098C, 0x0988, 0x3E38, 0x002C, 0x0010 +}; -static const uint16_t filter_8tap_64p_150[264] = { - 16380, 16020, 1032, 2756, 1032, 16020, 16380, 0, - 0, 16020, 992, 2756, 1068, 16024, 16376, 0, - 4, 16020, 952, 2752, 1108, 16024, 16372, 0, - 8, 16020, 916, 2748, 1148, 16028, 16368, 0, - 12, 16020, 876, 2744, 1184, 16032, 16364, 4, - 16, 16020, 840, 2740, 1224, 16036, 16356, 4, - 20, 16024, 800, 2732, 1264, 16040, 16352, 4, - 20, 16024, 764, 2724, 1304, 16044, 16348, 8, - 24, 16028, 728, 2716, 1344, 16052, 16340, 8, - 28, 16028, 692, 2704, 1380, 16056, 16336, 12, - 28, 16032, 656, 2696, 1420, 16064, 16328, 12, - 32, 16036, 620, 2684, 1460, 16072, 16324, 12, - 36, 16040, 584, 2668, 1500, 16080, 16316, 16, - 36, 16044, 548, 2656, 1536, 16088, 16308, 16, - 36, 16048, 516, 2640, 1576, 16096, 16304, 20, - 40, 16052, 480, 2624, 1612, 16108, 16296, 20, - 40, 16060, 448, 2608, 1652, 16120, 16288, 20, - 44, 16064, 416, 2588, 1692, 16132, 16280, 24, - 44, 16068, 384, 2568, 1728, 16144, 16276, 24, - 44, 16076, 352, 2548, 1764, 16156, 16268, 28, - 44, 16080, 320, 2528, 1804, 16168, 16260, 28, - 44, 16088, 292, 2508, 1840, 16184, 16252, 28, - 44, 16096, 264, 2484, 1876, 16200, 16244, 32, - 48, 16100, 232, 2460, 1912, 16216, 16236, 32, - 48, 16108, 204, 2436, 1948, 16232, 16228, 32, - 48, 16116, 176, 2412, 1980, 16248, 16220, 36, - 48, 16124, 152, 2384, 2016, 16264, 16216, 36, - 44, 16128, 124, 2356, 2052, 16284, 16208, 36, - 44, 16136, 100, 2328, 2084, 16304, 16200, 40, - 44, 16144, 72, 2300, 2116, 16324, 16192, 40, - 44, 16152, 48, 2272, 2148, 16344, 16184, 40, - 44, 16160, 24, 2244, 2180, 16364, 16176, 40, - 44, 16168, 4, 2212, 2212, 4, 16168, 44 }; +//========================================= +// = 8 +// = 64 +// = 1.49999 (input/output) +// = 0 +// = ModifiedLanczos +// = 1.10 +// = 1.12 +//========================================= +static const uint16_t filter_8tap_64p_149[264] = { + 0x0008, 0x3E8C, 0x03F8, 0x0AE8, 0x03F8, 0x3E8C, 0x0008, 0x0000, + 0x000C, 0x3E8C, 0x03D0, 0x0AE8, 0x0420, 0x3E90, 0x0000, 0x0000, + 0x000C, 0x3E8C, 0x03AC, 0x0AE8, 0x0444, 0x3E90, 0x0000, 0x0000, + 0x0010, 0x3E90, 0x0384, 0x0AE0, 0x046C, 0x3E94, 0x3FFC, 0x0000, + 0x0014, 0x3E90, 0x035C, 0x0ADC, 0x0494, 0x3E94, 0x3FF8, 0x0004, + 0x0018, 0x3E90, 0x0334, 0x0AD8, 0x04BC, 0x3E98, 0x3FF4, 0x0004, + 0x001C, 0x3E94, 0x0310, 0x0AD0, 0x04E4, 0x3E9C, 0x3FEC, 0x0004, + 0x0020, 0x3E98, 0x02E8, 0x0AC4, 0x050C, 0x3EA0, 0x3FE8, 0x0008, + 0x0020, 0x3E98, 0x02C4, 0x0AC0, 0x0534, 0x3EA4, 0x3FE4, 0x0008, + 0x0024, 0x3E9C, 0x02A0, 0x0AB4, 0x055C, 0x3EAC, 0x3FDC, 0x0008, + 0x0024, 0x3EA0, 0x027C, 0x0AA8, 0x0584, 0x3EB0, 0x3FD8, 0x000C, + 0x0028, 0x3EA4, 0x0258, 0x0A9C, 0x05AC, 0x3EB8, 0x3FD0, 0x000C, + 0x0028, 0x3EA8, 0x0234, 0x0A90, 0x05D4, 0x3EC0, 0x3FC8, 0x0010, + 0x002C, 0x3EAC, 0x0210, 0x0A80, 0x05FC, 0x3EC8, 0x3FC4, 0x0010, + 0x002C, 0x3EB4, 0x01F0, 0x0A70, 0x0624, 0x3ED0, 0x3FBC, 0x0010, + 0x002C, 0x3EB8, 0x01CC, 0x0A60, 0x064C, 0x3EDC, 0x3FB4, 0x0014, + 0x0030, 0x3EBC, 0x01A8, 0x0A50, 0x0674, 0x3EE4, 0x3FB0, 0x0014, + 0x0030, 0x3EC4, 0x0188, 0x0A38, 0x069C, 0x3EF0, 0x3FA8, 0x0018, + 0x0030, 0x3ECC, 0x0168, 0x0A28, 0x06C0, 0x3EFC, 0x3FA0, 0x0018, + 0x0030, 0x3ED0, 0x0148, 0x0A14, 0x06E8, 0x3F08, 0x3F98, 0x001C, + 0x0030, 0x3ED8, 0x012C, 0x0A00, 0x070C, 0x3F14, 0x3F90, 0x001C, + 0x0034, 0x3EE0, 0x0108, 0x09E4, 0x0734, 0x3F24, 0x3F8C, 0x001C, + 0x0034, 0x3EE4, 0x00EC, 0x09CC, 0x0758, 0x3F34, 0x3F84, 0x0020, + 0x0034, 0x3EEC, 0x00D0, 0x09B8, 0x077C, 0x3F40, 0x3F7C, 0x0020, + 0x0034, 0x3EF4, 0x00B4, 0x0998, 0x07A4, 0x3F50, 0x3F74, 0x0024, + 0x0030, 0x3EFC, 0x0098, 0x0980, 0x07C8, 0x3F64, 0x3F6C, 0x0024, + 0x0030, 0x3F04, 0x0080, 0x0968, 0x07E8, 0x3F74, 0x3F64, 0x0024, + 0x0030, 0x3F0C, 0x0060, 0x094C, 0x080C, 0x3F88, 0x3F5C, 0x0028, + 0x0030, 0x3F14, 0x0048, 0x0930, 0x0830, 0x3F98, 0x3F54, 0x0028, + 0x0030, 0x3F1C, 0x0030, 0x0914, 0x0850, 0x3FAC, 0x3F4C, 0x0028, + 0x0030, 0x3F24, 0x0018, 0x08F0, 0x0874, 0x3FC0, 0x3F44, 0x002C, + 0x002C, 0x3F2C, 0x0000, 0x08D4, 0x0894, 0x3FD8, 0x3F3C, 0x002C, + 0x002C, 0x3F34, 0x3FEC, 0x08B4, 0x08B4, 0x3FEC, 0x3F34, 0x002C +}; +//========================================= +// = 8 +// = 64 +// = 1.83332 (input/output) +// = 0 +// = ModifiedLanczos +// = 1.10 +// = 1.12 +//========================================= static const uint16_t filter_8tap_64p_183[264] = { - 16264, 16264, 1164, 2244, 1164, 16264, 16264, 0, - 16268, 16256, 1136, 2240, 1188, 16272, 16260, 0, - 16272, 16248, 1108, 2240, 1216, 16280, 16256, 0, - 16276, 16240, 1080, 2236, 1240, 16292, 16252, 0, - 16280, 16232, 1056, 2236, 1268, 16300, 16248, 0, - 16284, 16224, 1028, 2232, 1292, 16312, 16244, 0, - 16288, 16216, 1000, 2228, 1320, 16324, 16240, 0, - 16292, 16212, 976, 2224, 1344, 16336, 16236, 0, - 16296, 16204, 948, 2220, 1372, 16348, 16232, 0, - 16300, 16200, 920, 2212, 1396, 16360, 16228, 4, - 16304, 16196, 896, 2204, 1424, 16372, 16224, 4, - 16308, 16188, 868, 2200, 1448, 0, 16220, 4, - 16312, 16184, 844, 2192, 1472, 12, 16216, 4, - 16316, 16180, 816, 2184, 1500, 28, 16212, 4, - 16320, 16176, 792, 2172, 1524, 40, 16208, 4, - 16324, 16172, 764, 2164, 1548, 56, 16204, 0, - 16328, 16172, 740, 2156, 1572, 72, 16200, 0, - 16328, 16168, 712, 2144, 1596, 88, 16196, 0, - 16332, 16164, 688, 2132, 1620, 100, 16192, 0, - 16336, 16164, 664, 2120, 1644, 120, 16192, 0, - 16340, 16160, 640, 2108, 1668, 136, 16188, 0, - 16344, 16160, 616, 2096, 1688, 152, 16184, 0, - 16344, 16160, 592, 2080, 1712, 168, 16180, 0, - 16348, 16156, 568, 2068, 1736, 188, 16176, 16380, - 16352, 16156, 544, 2052, 1756, 204, 16176, 16380, - 16352, 16156, 520, 2036, 1780, 224, 16172, 16380, - 16356, 16156, 496, 2024, 1800, 244, 16172, 16380, - 16360, 16156, 472, 2008, 1820, 260, 16168, 16376, - 16360, 16156, 452, 1988, 1840, 280, 16164, 16376, - 16364, 16156, 428, 1972, 1860, 300, 16164, 16376, - 16364, 16156, 408, 1956, 1880, 320, 16164, 16372, - 16368, 16160, 384, 1936, 1900, 344, 16160, 16372, - 16368, 16160, 364, 1920, 1920, 364, 16160, 16368 }; + 0x3F88, 0x0048, 0x047C, 0x0768, 0x047C, 0x0048, 0x3F88, 0x0000, + 0x3F88, 0x003C, 0x0468, 0x076C, 0x0490, 0x0054, 0x3F84, 0x0000, + 0x3F8C, 0x0034, 0x0454, 0x0768, 0x04A4, 0x005C, 0x3F84, 0x0000, + 0x3F8C, 0x0028, 0x0444, 0x076C, 0x04B4, 0x0068, 0x3F80, 0x0000, + 0x3F90, 0x0020, 0x042C, 0x0768, 0x04C8, 0x0074, 0x3F80, 0x0000, + 0x3F90, 0x0018, 0x041C, 0x0764, 0x04DC, 0x0080, 0x3F7C, 0x0000, + 0x3F94, 0x0010, 0x0408, 0x075C, 0x04F0, 0x008C, 0x3F7C, 0x0000, + 0x3F94, 0x0004, 0x03F8, 0x0760, 0x0500, 0x0098, 0x3F7C, 0x3FFC, + 0x3F98, 0x0000, 0x03E0, 0x075C, 0x0514, 0x00A4, 0x3F78, 0x3FFC, + 0x3F9C, 0x3FF8, 0x03CC, 0x0754, 0x0528, 0x00B0, 0x3F78, 0x3FFC, + 0x3F9C, 0x3FF0, 0x03B8, 0x0754, 0x0538, 0x00BC, 0x3F78, 0x3FFC, + 0x3FA0, 0x3FE8, 0x03A4, 0x0750, 0x054C, 0x00CC, 0x3F74, 0x3FF8, + 0x3FA4, 0x3FE0, 0x0390, 0x074C, 0x055C, 0x00D8, 0x3F74, 0x3FF8, + 0x3FA4, 0x3FDC, 0x037C, 0x0744, 0x0570, 0x00E4, 0x3F74, 0x3FF8, + 0x3FA8, 0x3FD4, 0x0368, 0x0740, 0x0580, 0x00F4, 0x3F74, 0x3FF4, + 0x3FA8, 0x3FCC, 0x0354, 0x073C, 0x0590, 0x0104, 0x3F74, 0x3FF4, + 0x3FAC, 0x3FC8, 0x0340, 0x0730, 0x05A4, 0x0110, 0x3F74, 0x3FF4, + 0x3FB0, 0x3FC0, 0x0330, 0x0728, 0x05B4, 0x0120, 0x3F74, 0x3FF0, + 0x3FB0, 0x3FBC, 0x031C, 0x0724, 0x05C4, 0x0130, 0x3F70, 0x3FF0, + 0x3FB4, 0x3FB4, 0x0308, 0x0720, 0x05D4, 0x013C, 0x3F70, 0x3FF0, + 0x3FB8, 0x3FB0, 0x02F4, 0x0714, 0x05E4, 0x014C, 0x3F74, 0x3FEC, + 0x3FB8, 0x3FAC, 0x02E0, 0x0708, 0x05F8, 0x015C, 0x3F74, 0x3FEC, + 0x3FBC, 0x3FA8, 0x02CC, 0x0704, 0x0604, 0x016C, 0x3F74, 0x3FE8, + 0x3FC0, 0x3FA0, 0x02BC, 0x06F8, 0x0614, 0x017C, 0x3F74, 0x3FE8, + 0x3FC0, 0x3F9C, 0x02A8, 0x06F4, 0x0624, 0x018C, 0x3F74, 0x3FE4, + 0x3FC4, 0x3F98, 0x0294, 0x06E8, 0x0634, 0x019C, 0x3F74, 0x3FE4, + 0x3FC8, 0x3F94, 0x0284, 0x06D8, 0x0644, 0x01AC, 0x3F78, 0x3FE0, + 0x3FC8, 0x3F90, 0x0270, 0x06D4, 0x0650, 0x01BC, 0x3F78, 0x3FE0, + 0x3FCC, 0x3F8C, 0x025C, 0x06C8, 0x0660, 0x01D0, 0x3F78, 0x3FDC, + 0x3FCC, 0x3F8C, 0x024C, 0x06B8, 0x066C, 0x01E0, 0x3F7C, 0x3FDC, + 0x3FD0, 0x3F88, 0x0238, 0x06B0, 0x067C, 0x01F0, 0x3F7C, 0x3FD8, + 0x3FD4, 0x3F84, 0x0228, 0x069C, 0x0688, 0x0204, 0x3F80, 0x3FD8, + 0x3FD4, 0x3F84, 0x0214, 0x0694, 0x0694, 0x0214, 0x3F84, 0x3FD4 +}; const uint16_t *get_filter_3tap_16p(struct fixed31_32 ratio) { if (ratio.value < dc_fixpt_one.value) return filter_3tap_16p_upscale; else if (ratio.value < dc_fixpt_from_fraction(4, 3).value) - return filter_3tap_16p_117; + return filter_3tap_16p_116; else if (ratio.value < dc_fixpt_from_fraction(5, 3).value) - return filter_3tap_16p_150; + return filter_3tap_16p_149; else return filter_3tap_16p_183; } @@ -1029,9 +1355,9 @@ const uint16_t *get_filter_3tap_64p(struct fixed31_32 ratio) if (ratio.value < dc_fixpt_one.value) return filter_3tap_64p_upscale; else if (ratio.value < dc_fixpt_from_fraction(4, 3).value) - return filter_3tap_64p_117; + return filter_3tap_64p_116; else if (ratio.value < dc_fixpt_from_fraction(5, 3).value) - return filter_3tap_64p_150; + return filter_3tap_64p_149; else return filter_3tap_64p_183; } @@ -1041,9 +1367,9 @@ const uint16_t *get_filter_4tap_16p(struct fixed31_32 ratio) if (ratio.value < dc_fixpt_one.value) return filter_4tap_16p_upscale; else if (ratio.value < dc_fixpt_from_fraction(4, 3).value) - return filter_4tap_16p_117; + return filter_4tap_16p_116; else if (ratio.value < dc_fixpt_from_fraction(5, 3).value) - return filter_4tap_16p_150; + return filter_4tap_16p_149; else return filter_4tap_16p_183; } @@ -1053,9 +1379,9 @@ const uint16_t *get_filter_4tap_64p(struct fixed31_32 ratio) if (ratio.value < dc_fixpt_one.value) return filter_4tap_64p_upscale; else if (ratio.value < dc_fixpt_from_fraction(4, 3).value) - return filter_4tap_64p_117; + return filter_4tap_64p_116; else if (ratio.value < dc_fixpt_from_fraction(5, 3).value) - return filter_4tap_64p_150; + return filter_4tap_64p_149; else return filter_4tap_64p_183; } @@ -1065,9 +1391,9 @@ const uint16_t *get_filter_5tap_64p(struct fixed31_32 ratio) if (ratio.value < dc_fixpt_one.value) return filter_5tap_64p_upscale; else if (ratio.value < dc_fixpt_from_fraction(4, 3).value) - return filter_5tap_64p_117; + return filter_5tap_64p_116; else if (ratio.value < dc_fixpt_from_fraction(5, 3).value) - return filter_5tap_64p_150; + return filter_5tap_64p_149; else return filter_5tap_64p_183; } @@ -1077,9 +1403,9 @@ const uint16_t *get_filter_6tap_64p(struct fixed31_32 ratio) if (ratio.value < dc_fixpt_one.value) return filter_6tap_64p_upscale; else if (ratio.value < dc_fixpt_from_fraction(4, 3).value) - return filter_6tap_64p_117; + return filter_6tap_64p_116; else if (ratio.value < dc_fixpt_from_fraction(5, 3).value) - return filter_6tap_64p_150; + return filter_6tap_64p_149; else return filter_6tap_64p_183; } @@ -1089,9 +1415,9 @@ const uint16_t *get_filter_7tap_64p(struct fixed31_32 ratio) if (ratio.value < dc_fixpt_one.value) return filter_7tap_64p_upscale; else if (ratio.value < dc_fixpt_from_fraction(4, 3).value) - return filter_7tap_64p_117; + return filter_7tap_64p_116; else if (ratio.value < dc_fixpt_from_fraction(5, 3).value) - return filter_7tap_64p_150; + return filter_7tap_64p_149; else return filter_7tap_64p_183; } @@ -1101,9 +1427,9 @@ const uint16_t *get_filter_8tap_64p(struct fixed31_32 ratio) if (ratio.value < dc_fixpt_one.value) return filter_8tap_64p_upscale; else if (ratio.value < dc_fixpt_from_fraction(4, 3).value) - return filter_8tap_64p_117; + return filter_8tap_64p_116; else if (ratio.value < dc_fixpt_from_fraction(5, 3).value) - return filter_8tap_64p_150; + return filter_8tap_64p_149; else return filter_8tap_64p_183; } diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_scl_filters_old.c b/drivers/gpu/drm/amd/display/dc/dce/dce_scl_filters_old.c new file mode 100644 index 000000000000..bb0e1b80ec3c --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_scl_filters_old.c @@ -0,0 +1,25 @@ +/* + * Copyright 2012-16 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + -- cgit From 017b3e56f8995182f26b7c9018faa15b847b7cd9 Mon Sep 17 00:00:00 2001 From: Alvin Lee Date: Wed, 22 Jan 2020 14:56:35 -0500 Subject: drm/amd/display: Update TX masks correctly [Why] Bugs occur when TX interrupt comes in when no USB-C on board. [How] Check PHY for USB-C before enabling TX interrupt in DMCU FW. Signed-off-by: Alvin Lee Reviewed-by: Jun Lei Acked-by: Rodrigo Siqueira Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'drivers/gpu/drm/amd/display') diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c b/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c index 30d953acd016..f0cebe721bcc 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c @@ -378,6 +378,11 @@ static bool dcn10_dmcu_init(struct dmcu *dmcu) struct dce_dmcu *dmcu_dce = TO_DCE_DMCU(dmcu); const struct dc_config *config = &dmcu->ctx->dc->config; bool status = false; + struct dc_context *ctx = dmcu->ctx; + unsigned int i; + // 5 4 3 2 1 0 + // F E D C B A - bit 0 is A, bit 5 is F + unsigned int tx_interrupt_mask = 0; PERF_TRACE(); /* Definition of DC_DMCU_SCRATCH @@ -387,6 +392,15 @@ static bool dcn10_dmcu_init(struct dmcu *dmcu) */ dmcu->dmcu_state = REG_READ(DC_DMCU_SCRATCH); + for (i = 0; i < ctx->dc->link_count; i++) { + if (ctx->dc->links[i]->link_enc->features.flags.bits.DP_IS_USB_C) { + if (ctx->dc->links[i]->link_enc->transmitter >= TRANSMITTER_UNIPHY_A && + ctx->dc->links[i]->link_enc->transmitter <= TRANSMITTER_UNIPHY_F) { + tx_interrupt_mask |= 1 << ctx->dc->links[i]->link_enc->transmitter; + } + } + } + switch (dmcu->dmcu_state) { case DMCU_UNLOADED: status = false; @@ -401,6 +415,8 @@ static bool dcn10_dmcu_init(struct dmcu *dmcu) /* Set backlight ramping stepsize */ REG_WRITE(MASTER_COMM_DATA_REG2, abm_gain_stepsize); + REG_WRITE(MASTER_COMM_DATA_REG3, tx_interrupt_mask); + /* Set command to initialize microcontroller */ REG_UPDATE(MASTER_COMM_CMD_REG, MASTER_COMM_CMD_REG_BYTE0, MCP_INIT_DMCU); -- cgit From 31a7f4bb17badca605469362463a2c21863a43cf Mon Sep 17 00:00:00 2001 From: Hersen Wu Date: Wed, 5 Feb 2020 14:58:53 -0500 Subject: drm/amd/display: dmub back door load Signed-off-by: Hersen Wu Signed-off-by: Jerry (Fangzhi) Zuo Reviewed-by: Hersen Wu Acked-by: Rodrigo Siqueira Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'drivers/gpu/drm/amd/display') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index f4e4c42341b9..985ffceb6774 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -823,6 +823,10 @@ static int dm_dmub_hw_init(struct amdgpu_device *adev) hw_params.fb_base = adev->gmc.fb_start; hw_params.fb_offset = adev->gmc.aper_base; + /* backdoor load firmware and trigger dmub running */ + if (adev->firmware.load_type != AMDGPU_FW_LOAD_PSP) + hw_params.load_inst_const = true; + if (dmcu) hw_params.psp_version = dmcu->psp_version; @@ -1192,11 +1196,6 @@ static int dm_dmub_sw_init(struct amdgpu_device *adev) return 0; } - if (adev->firmware.load_type != AMDGPU_FW_LOAD_PSP) { - DRM_WARN("Only PSP firmware loading is supported for DMUB\n"); - return 0; - } - hdr = (const struct dmcub_firmware_header_v1_0 *)adev->dm.dmub_fw->data; adev->firmware.ucode[AMDGPU_UCODE_ID_DMCUB].ucode_id = AMDGPU_UCODE_ID_DMCUB; -- cgit From ddde28a5f31613c535609805296fd32367850390 Mon Sep 17 00:00:00 2001 From: Hersen Wu Date: Wed, 5 Feb 2020 17:48:39 -0500 Subject: drm/amd/display: DMUB Firmware Load by PSP Signed-off-by: Hersen Wu Signed-off-by: Jerry (Fangzhi) Zuo Reviewed-by: Hersen Wu Acked-by: Rodrigo Siqueira Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) (limited to 'drivers/gpu/drm/amd/display') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 985ffceb6774..7283c990d130 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -801,10 +801,20 @@ static int dm_dmub_hw_init(struct amdgpu_device *adev) fw_bss_data_size = le32_to_cpu(hdr->bss_data_bytes); - memcpy(fb_info->fb[DMUB_WINDOW_0_INST_CONST].cpu_addr, fw_inst_const, - fw_inst_const_size); + /* if adev->firmware.load_type == AMDGPU_FW_LOAD_PSP, + * amdgpu_ucode_init_single_fw will load dmub firmware + * fw_inst_const part to cw0; otherwise, the firmware back door load + * will be done by dm_dmub_hw_init + */ + if (adev->firmware.load_type != AMDGPU_FW_LOAD_PSP) { + memcpy(fb_info->fb[DMUB_WINDOW_0_INST_CONST].cpu_addr, fw_inst_const, + fw_inst_const_size); + } + memcpy(fb_info->fb[DMUB_WINDOW_2_BSS_DATA].cpu_addr, fw_bss_data, fw_bss_data_size); + + /* Copy firmware bios info into FB memory. */ memcpy(fb_info->fb[DMUB_WINDOW_3_VBIOS].cpu_addr, adev->bios, adev->bios_size); -- cgit From 3c9de4da021c7c2aaa421b5c37057890348bd58a Mon Sep 17 00:00:00 2001 From: Alvin Lee Date: Tue, 4 Feb 2020 15:19:21 -0500 Subject: drm/amd/display: Disable PG on NV12 [Why] According to HW team, PG is dropped for NV12, but programming the registers will still cause power to be consumed, so don't program for NV12. [How] Set function pointer to NULL if NV12 Signed-off-by: Alvin Lee Reviewed-by: Jun Lei Acked-by: Rodrigo Siqueira Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 7 ++++--- drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c | 9 +++++++++ 2 files changed, 13 insertions(+), 3 deletions(-) (limited to 'drivers/gpu/drm/amd/display') diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index af40ea5765f4..53083e658fe0 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -1268,7 +1268,8 @@ void dcn10_init_hw(struct dc *dc) } //Enable ability to power gate / don't force power on permanently - hws->funcs.enable_power_gating_plane(hws, true); + if (hws->funcs.enable_power_gating_plane) + hws->funcs.enable_power_gating_plane(hws, true); return; } @@ -1385,8 +1386,8 @@ void dcn10_init_hw(struct dc *dc) REG_UPDATE(DCFCLK_CNTL, DCFCLK_GATE_DIS, 0); } - - hws->funcs.enable_power_gating_plane(dc->hwseq, true); + if (hws->funcs.enable_power_gating_plane) + hws->funcs.enable_power_gating_plane(dc->hwseq, true); if (dc->clk_mgr->funcs->notify_wm_ranges) dc->clk_mgr->funcs->notify_wm_ranges(dc->clk_mgr); diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c index 1061faccec9c..080d4581a93d 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c @@ -3760,6 +3760,15 @@ static bool dcn20_resource_construct( dcn20_hw_sequencer_construct(dc); + // IF NV12, set PG function pointer to NULL. It's not that + // PG isn't supported for NV12, it's that we don't want to + // program the registers because that will cause more power + // to be consumed. We could have created dcn20_init_hw to get + // the same effect by checking ASIC rev, but there was a + // request at some point to not check ASIC rev on hw sequencer. + if (ASICREV_IS_NAVI12_P(dc->ctx->asic_id.hw_internal_rev)) + dc->hwseq->funcs.enable_power_gating_plane = NULL; + dc->caps.max_planes = pool->base.pipe_count; for (i = 0; i < dc->caps.max_planes; ++i) -- cgit From 20a5e52f37e71e51defb09f8fd6ad5d84bcd6c90 Mon Sep 17 00:00:00 2001 From: Nicholas Kazlauskas Date: Tue, 28 Jan 2020 15:15:10 -0500 Subject: drm/amd/display: Wait for DMCUB to finish loading before executing commands [Why] When we execute the first command for ASIC_INIT for command table offloading we can hit a timing scenario such that the interrupts for the inbox wptr haven't been enabled yet and the first command is ignored until the second command is sent. [How] This happens when either the SCRATCH0 is already the correct status code or autoload check is unsupported. Clear SCRATCH0 during reset. Also ensure that we don't accidentally reset the ASIC again in case of a hang by clearing GPINT while we're at it. Signed-off-by: Nicholas Kazlauskas Reviewed-by: Chris Park Acked-by: Rodrigo Siqueira Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dmub/src/dmub_dcn20.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers/gpu/drm/amd/display') diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn20.c b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn20.c index 993e47e99fbe..63bb9e2c81de 100644 --- a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn20.c +++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn20.c @@ -116,6 +116,10 @@ void dmub_dcn20_reset(struct dmub_srv *dmub) break; } + /* Clear the GPINT command manually so we don't reset again. */ + cmd.all = 0; + dmub->hw_funcs.set_gpint(dmub, cmd); + /* Force reset in case we timed out, DMCUB is likely hung. */ } @@ -124,6 +128,7 @@ void dmub_dcn20_reset(struct dmub_srv *dmub) REG_UPDATE(MMHUBBUB_SOFT_RESET, DMUIF_SOFT_RESET, 1); REG_WRITE(DMCUB_INBOX1_RPTR, 0); REG_WRITE(DMCUB_INBOX1_WPTR, 0); + REG_WRITE(DMCUB_SCRATCH0, 0); } void dmub_dcn20_reset_release(struct dmub_srv *dmub) -- cgit From 9a6ed547090c41cc4c64df1f556314b0cbdc781f Mon Sep 17 00:00:00 2001 From: Nicholas Kazlauskas Date: Tue, 28 Jan 2020 15:14:07 -0500 Subject: drm/amd/display: Don't ask PSP to load DMCUB for backdoor load [Why] If we're doing backdoor load then do it entirely ourselves without invoking any of the frontdoor path to avoid potential issues with outdated tOS. [How] Check the load type and don't pass it to base if we don't want it loaded. Signed-off-by: Nicholas Kazlauskas Reviewed-by: Hersen Wu Acked-by: Rodrigo Siqueira Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) (limited to 'drivers/gpu/drm/amd/display') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 7283c990d130..d09fabeee58f 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -1207,16 +1207,20 @@ static int dm_dmub_sw_init(struct amdgpu_device *adev) } hdr = (const struct dmcub_firmware_header_v1_0 *)adev->dm.dmub_fw->data; - adev->firmware.ucode[AMDGPU_UCODE_ID_DMCUB].ucode_id = - AMDGPU_UCODE_ID_DMCUB; - adev->firmware.ucode[AMDGPU_UCODE_ID_DMCUB].fw = adev->dm.dmub_fw; - adev->firmware.fw_size += - ALIGN(le32_to_cpu(hdr->inst_const_bytes), PAGE_SIZE); - adev->dm.dmcub_fw_version = le32_to_cpu(hdr->header.ucode_version); + if (adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) { + adev->firmware.ucode[AMDGPU_UCODE_ID_DMCUB].ucode_id = + AMDGPU_UCODE_ID_DMCUB; + adev->firmware.ucode[AMDGPU_UCODE_ID_DMCUB].fw = + adev->dm.dmub_fw; + adev->firmware.fw_size += + ALIGN(le32_to_cpu(hdr->inst_const_bytes), PAGE_SIZE); - DRM_INFO("Loading DMUB firmware via PSP: version=0x%08X\n", - adev->dm.dmcub_fw_version); + DRM_INFO("Loading DMUB firmware via PSP: version=0x%08X\n", + adev->dm.dmcub_fw_version); + } + + adev->dm.dmcub_fw_version = le32_to_cpu(hdr->header.ucode_version); adev->dm.dmub_srv = kzalloc(sizeof(*adev->dm.dmub_srv), GFP_KERNEL); dmub_srv = adev->dm.dmub_srv; -- cgit From 5ea239312725ce11ec311472f4d71504d26d67e9 Mon Sep 17 00:00:00 2001 From: Roman Li Date: Wed, 5 Feb 2020 09:39:41 -0500 Subject: drm/amd/display: Add dmcu f/w loading for NV12 [Why] We need DMCU for features like PSR and ABM. [How] Add path to dmcu firmware binary and load it for Navi12. Signed-off-by: Roman Li Reviewed-by: Hersen Wu Acked-by: Rodrigo Siqueira Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'drivers/gpu/drm/amd/display') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index d09fabeee58f..e768a31441cc 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -98,6 +98,9 @@ MODULE_FIRMWARE(FIRMWARE_RENOIR_DMUB); #define FIRMWARE_RAVEN_DMCU "amdgpu/raven_dmcu.bin" MODULE_FIRMWARE(FIRMWARE_RAVEN_DMCU); +#define FIRMWARE_NAVI12_DMCU "amdgpu/navi12_dmcu.bin" +MODULE_FIRMWARE(FIRMWARE_NAVI12_DMCU); + /* Number of bytes in PSP header for firmware. */ #define PSP_HEADER_BYTES 0x100 @@ -1093,9 +1096,11 @@ static int load_dmcu_fw(struct amdgpu_device *adev) case CHIP_VEGA20: case CHIP_NAVI10: case CHIP_NAVI14: - case CHIP_NAVI12: case CHIP_RENOIR: return 0; + case CHIP_NAVI12: + fw_name_dmcu = FIRMWARE_NAVI12_DMCU; + break; case CHIP_RAVEN: if (ASICREV_IS_PICASSO(adev->external_rev_id)) fw_name_dmcu = FIRMWARE_RAVEN_DMCU; -- cgit From 586ec5dc5c8ea28f46b9e27415dfd0f4de01849e Mon Sep 17 00:00:00 2001 From: Samson Tam Date: Tue, 4 Feb 2020 14:26:30 -0500 Subject: drm/amd/display: do not force UCLK DPM to stay at highest state during display off in DCN2 [Why] Add optimization to allow pstate change support when all displays are off in DCN2. [How] Add clk_mgr_helper_get_active_plane_cnt() to sum plane_count for all valid stream_status[]. If plane_count is 0, then there are no active or virtual streams present. Use plane_count == 0 as extra condition to enable p_state_change_support in dcn2_update_clocks(). Signed-off-by: Samson Tam Reviewed-by: Jun Lei Acked-by: Rodrigo Siqueira Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/clk_mgr/clk_mgr.c | 19 +++++++++++++++++++ .../drm/amd/display/dc/clk_mgr/dcn20/dcn20_clk_mgr.c | 8 ++++++-- .../gpu/drm/amd/display/dc/inc/hw/clk_mgr_internal.h | 4 ++++ 3 files changed, 29 insertions(+), 2 deletions(-) (limited to 'drivers/gpu/drm/amd/display') diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/clk_mgr.c index a78e5c74c79c..2f43f1618db8 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/clk_mgr.c @@ -63,6 +63,25 @@ int clk_mgr_helper_get_active_display_cnt( return display_count; } +int clk_mgr_helper_get_active_plane_cnt( + struct dc *dc, + struct dc_state *context) +{ + int i, total_plane_count; + + total_plane_count = 0; + for (i = 0; i < context->stream_count; i++) { + const struct dc_stream_status stream_status = context->stream_status[i]; + + /* + * Sum up plane_count for all streams ( active and virtual ). + */ + total_plane_count += stream_status.plane_count; + } + + return total_plane_count; +} + void clk_mgr_exit_optimized_pwr_state(const struct dc *dc, struct clk_mgr *clk_mgr) { struct dc_link *edp_link = get_edp_link(dc); diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn20/dcn20_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn20/dcn20_clk_mgr.c index 49ce46b543ea..68a1120ff674 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn20/dcn20_clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn20/dcn20_clk_mgr.c @@ -158,6 +158,8 @@ void dcn2_update_clocks(struct clk_mgr *clk_mgr_base, bool dpp_clock_lowered = false; struct dmcu *dmcu = clk_mgr_base->ctx->dc->res_pool->dmcu; bool force_reset = false; + bool p_state_change_support; + int total_plane_count; if (dc->work_arounds.skip_clock_update) return; @@ -213,9 +215,11 @@ void dcn2_update_clocks(struct clk_mgr *clk_mgr_base, pp_smu->set_hard_min_socclk_by_freq(&pp_smu->pp_smu, clk_mgr_base->clks.socclk_khz / 1000); } - if (should_update_pstate_support(safe_to_lower, new_clocks->p_state_change_support, clk_mgr_base->clks.p_state_change_support)) { + total_plane_count = clk_mgr_helper_get_active_plane_cnt(dc, context); + p_state_change_support = new_clocks->p_state_change_support || (total_plane_count == 0); + if (should_update_pstate_support(safe_to_lower, p_state_change_support, clk_mgr_base->clks.p_state_change_support)) { clk_mgr_base->clks.prev_p_state_change_support = clk_mgr_base->clks.p_state_change_support; - clk_mgr_base->clks.p_state_change_support = new_clocks->p_state_change_support; + clk_mgr_base->clks.p_state_change_support = p_state_change_support; if (pp_smu && pp_smu->set_pstate_handshake_support) pp_smu->set_pstate_handshake_support(&pp_smu->pp_smu, clk_mgr_base->clks.p_state_change_support); } diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/clk_mgr_internal.h b/drivers/gpu/drm/amd/display/dc/inc/hw/clk_mgr_internal.h index 862952c0286a..9311d0de377f 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/clk_mgr_internal.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/clk_mgr_internal.h @@ -296,6 +296,10 @@ int clk_mgr_helper_get_active_display_cnt( struct dc *dc, struct dc_state *context); +int clk_mgr_helper_get_active_plane_cnt( + struct dc *dc, + struct dc_state *context); + #endif //__DAL_CLK_MGR_INTERNAL_H__ -- cgit From 0062972b9d9f888d0273c6496769d02e8f509135 Mon Sep 17 00:00:00 2001 From: Peikang Zhang Date: Fri, 7 Feb 2020 16:53:28 -0500 Subject: drm/amd/display: System crashes when add_ptb_to_table() gets called [Why] Unused VMIDs were not evicted correctly [How] 1. evict_vmids() logic was fixed; 2. Added boundary check for add_ptb_to_table() and clear_entry_from_vmid_table() to avoid crash caused by array out of boundary; 3. For mod_vmid_get_for_ptb(), vimd is changed from unsigned to signed due to vimd is signed. Signed-off-by: Peikang Zhang Reviewed-by: Aric Cyr Acked-by: Rodrigo Siqueira Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/modules/vmid/vmid.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) (limited to 'drivers/gpu/drm/amd/display') diff --git a/drivers/gpu/drm/amd/display/modules/vmid/vmid.c b/drivers/gpu/drm/amd/display/modules/vmid/vmid.c index f0a153704f6e..00f132f8ad55 100644 --- a/drivers/gpu/drm/amd/display/modules/vmid/vmid.c +++ b/drivers/gpu/drm/amd/display/modules/vmid/vmid.c @@ -40,14 +40,18 @@ struct core_vmid { static void add_ptb_to_table(struct core_vmid *core_vmid, unsigned int vmid, uint64_t ptb) { - core_vmid->ptb_assigned_to_vmid[vmid] = ptb; - core_vmid->num_vmids_available--; + if (vmid < MAX_VMID) { + core_vmid->ptb_assigned_to_vmid[vmid] = ptb; + core_vmid->num_vmids_available--; + } } static void clear_entry_from_vmid_table(struct core_vmid *core_vmid, unsigned int vmid) { - core_vmid->ptb_assigned_to_vmid[vmid] = 0; - core_vmid->num_vmids_available++; + if (vmid < MAX_VMID) { + core_vmid->ptb_assigned_to_vmid[vmid] = 0; + core_vmid->num_vmids_available++; + } } static void evict_vmids(struct core_vmid *core_vmid) @@ -57,7 +61,7 @@ static void evict_vmids(struct core_vmid *core_vmid) // At this point any positions with value 0 are unused vmids, evict them for (i = 1; i < core_vmid->num_vmid; i++) { - if (ord & (1u << i)) + if (!(ord & (1u << i))) clear_entry_from_vmid_table(core_vmid, i); } } @@ -91,7 +95,7 @@ static int get_next_available_vmid(struct core_vmid *core_vmid) uint8_t mod_vmid_get_for_ptb(struct mod_vmid *mod_vmid, uint64_t ptb) { struct core_vmid *core_vmid = MOD_VMID_TO_CORE(mod_vmid); - unsigned int vmid = 0; + int vmid = 0; // Physical address gets vmid 0 if (ptb == 0) -- cgit From 3fc6376ed6f2f67bc9fb0c7a3cf07967d6aa6216 Mon Sep 17 00:00:00 2001 From: Aric Cyr Date: Sun, 9 Feb 2020 12:31:25 -0500 Subject: drm/amd/display: Only round InfoFrame refresh rates [Why] When calculating nominal refresh rates, don't round. Only the VSIF needs to be rounded. [How] Revert rounding change for nominal and just round when forming the FreeSync VSIF. Signed-off-by: Aric Cyr Reviewed-by: Anthony Koo Acked-by: Rodrigo Siqueira Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/modules/freesync/freesync.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) (limited to 'drivers/gpu/drm/amd/display') diff --git a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c index b9992ebf77a6..4e542826cd26 100644 --- a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c +++ b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c @@ -524,12 +524,12 @@ static void build_vrr_infopacket_data(const struct mod_vrr_params *vrr, infopacket->sb[6] |= 0x04; /* PB7 = FreeSync Minimum refresh rate (Hz) */ - infopacket->sb[7] = (unsigned char)(vrr->min_refresh_in_uhz / 1000000); + infopacket->sb[7] = (unsigned char)((vrr->min_refresh_in_uhz + 500000) / 1000000); /* PB8 = FreeSync Maximum refresh rate (Hz) * Note: We should never go above the field rate of the mode timing set. */ - infopacket->sb[8] = (unsigned char)(vrr->max_refresh_in_uhz / 1000000); + infopacket->sb[8] = (unsigned char)((vrr->max_refresh_in_uhz + 500000) / 1000000); //FreeSync HDR @@ -747,10 +747,6 @@ void mod_freesync_build_vrr_params(struct mod_freesync *mod_freesync, nominal_field_rate_in_uhz = mod_freesync_calc_nominal_field_rate(stream); - /* Rounded to the nearest Hz */ - nominal_field_rate_in_uhz = 1000000ULL * - div_u64(nominal_field_rate_in_uhz + 500000, 1000000); - min_refresh_in_uhz = in_config->min_refresh_in_uhz; max_refresh_in_uhz = in_config->max_refresh_in_uhz; -- cgit From 493ba6611daa4245893ecf41c8ac3af1c8dd7df8 Mon Sep 17 00:00:00 2001 From: Aric Cyr Date: Sun, 9 Feb 2020 21:06:00 -0500 Subject: drm/amd/display: 3.2.73 Signed-off-by: Aric Cyr Reviewed-by: Aric Cyr Acked-by: Rodrigo Siqueira Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu/drm/amd/display') diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index f77b3acfeb06..b3f6311d3564 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -39,7 +39,7 @@ #include "inc/hw/dmcu.h" #include "dml/display_mode_lib.h" -#define DC_VER "3.2.72" +#define DC_VER "3.2.73" #define MAX_SURFACES 3 #define MAX_PLANES 6 -- cgit From 63a85ff6c35d8a7aaf0fb60ddbab93530d495bf3 Mon Sep 17 00:00:00 2001 From: Bhawanpreet Lakha Date: Fri, 7 Feb 2020 11:02:26 -0500 Subject: drm/amd/display: Fix HDMI repeater authentication when the rxstatus split was done the index was incorrect. This lead to HDMI repeater authentication failure for HDCP2.X So fix it Fixes: 302169003733 ("drm/amd/display: split rxstatus for hdmi and dp") Signed-off-by: Bhawanpreet Lakha Reviewed-by: Wenjing Liu Acked-by: Rodrigo Siqueira Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/modules/hdcp/hdcp2_execution.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/gpu/drm/amd/display') diff --git a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp2_execution.c b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp2_execution.c index 340df6d406f9..491c00f48026 100644 --- a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp2_execution.c +++ b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp2_execution.c @@ -34,7 +34,7 @@ static inline enum mod_hdcp_status check_receiver_id_list_ready(struct mod_hdcp if (is_dp_hdcp(hdcp)) is_ready = HDCP_2_2_DP_RXSTATUS_READY(hdcp->auth.msg.hdcp2.rxstatus_dp) ? 1 : 0; else - is_ready = (HDCP_2_2_HDMI_RXSTATUS_READY(hdcp->auth.msg.hdcp2.rxstatus[0]) && + is_ready = (HDCP_2_2_HDMI_RXSTATUS_READY(hdcp->auth.msg.hdcp2.rxstatus[1]) && (HDCP_2_2_HDMI_RXSTATUS_MSG_SZ_HI(hdcp->auth.msg.hdcp2.rxstatus[1]) << 8 | hdcp->auth.msg.hdcp2.rxstatus[0])) ? 1 : 0; return is_ready ? MOD_HDCP_STATUS_SUCCESS : @@ -67,7 +67,7 @@ static inline enum mod_hdcp_status check_reauthentication_request( MOD_HDCP_STATUS_HDCP2_REAUTH_REQUEST : MOD_HDCP_STATUS_SUCCESS; else - ret = HDCP_2_2_HDMI_RXSTATUS_REAUTH_REQ(hdcp->auth.msg.hdcp2.rxstatus[0]) ? + ret = HDCP_2_2_HDMI_RXSTATUS_REAUTH_REQ(hdcp->auth.msg.hdcp2.rxstatus[1]) ? MOD_HDCP_STATUS_HDCP2_REAUTH_REQUEST : MOD_HDCP_STATUS_SUCCESS; return ret; -- cgit From accde06fcb7fd82abdfa77ecf4dc63d724a6d9bf Mon Sep 17 00:00:00 2001 From: Anthony Koo Date: Wed, 5 Feb 2020 20:47:41 -0500 Subject: drm/amd/display: Add function pointers for panel related hw functions [Why] Make panel backlight and power on/off functions into hardware specific function pointers [How] Add function pointers for panel related hw functions - is_panel_powered_on - is_panel_backlight_on Signed-off-by: Anthony Koo Reviewed-by: Aric Cyr Acked-by: Rodrigo Siqueira Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c | 15 ++++++++++----- .../gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.h | 4 ++++ drivers/gpu/drm/amd/display/dc/dcn10/dcn10_init.c | 2 ++ drivers/gpu/drm/amd/display/dc/dcn20/dcn20_init.c | 2 ++ drivers/gpu/drm/amd/display/dc/dcn21/dcn21_init.c | 2 ++ drivers/gpu/drm/amd/display/dc/inc/hw_sequencer_private.h | 2 ++ 6 files changed, 22 insertions(+), 5 deletions(-) (limited to 'drivers/gpu/drm/amd/display') diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 28b681b33f7a..0976e378659f 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -698,8 +698,10 @@ void dce110_enable_stream(struct pipe_ctx *pipe_ctx) } /*todo: cloned in stream enc, fix*/ -static bool is_panel_backlight_on(struct dce_hwseq *hws) +bool dce110_is_panel_backlight_on(struct dc_link *link) { + struct dc_context *ctx = link->ctx; + struct dce_hwseq *hws = ctx->dc->hwseq; uint32_t value; REG_GET(LVTMA_PWRSEQ_CNTL, LVTMA_BLON, &value); @@ -707,11 +709,12 @@ static bool is_panel_backlight_on(struct dce_hwseq *hws) return value; } -static bool is_panel_powered_on(struct dce_hwseq *hws) +bool dce110_is_panel_powered_on(struct dc_link *link) { + struct dc_context *ctx = link->ctx; + struct dce_hwseq *hws = ctx->dc->hwseq; uint32_t pwr_seq_state, dig_on, dig_on_ovrd; - REG_GET(LVTMA_PWRSEQ_STATE, LVTMA_PWRSEQ_TARGET_STATE_R, &pwr_seq_state); REG_GET_2(LVTMA_PWRSEQ_CNTL, LVTMA_DIGON, &dig_on, LVTMA_DIGON_OVRD, &dig_on_ovrd); @@ -818,7 +821,7 @@ void dce110_edp_power_control( return; } - if (power_up != is_panel_powered_on(hwseq)) { + if (power_up != hwseq->funcs.is_panel_powered_on(link)) { /* Send VBIOS command to prompt eDP panel power */ if (power_up) { unsigned long long current_ts = dm_get_timestamp(ctx); @@ -898,7 +901,7 @@ void dce110_edp_backlight_control( return; } - if (enable && is_panel_backlight_on(hws)) { + if (enable && hws->funcs.is_panel_backlight_on(link)) { DC_LOG_HW_RESUME_S3( "%s: panel already powered up. Do nothing.\n", __func__); @@ -2764,6 +2767,8 @@ static const struct hwseq_private_funcs dce110_private_funcs = { .disable_stream_gating = NULL, .enable_stream_gating = NULL, .edp_backlight_control = dce110_edp_backlight_control, + .is_panel_backlight_on = dce110_is_panel_backlight_on, + .is_panel_powered_on = dce110_is_panel_powered_on, }; void dce110_hw_sequencer_construct(struct dc *dc) diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.h index 26a9c14a58b1..34be166e8ff0 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.h @@ -85,5 +85,9 @@ void dce110_edp_wait_for_hpd_ready( struct dc_link *link, bool power_up); +bool dce110_is_panel_backlight_on(struct dc_link *link); + +bool dce110_is_panel_powered_on(struct dc_link *link); + #endif /* __DC_HWSS_DCE110_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_init.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_init.c index b88ef9703b2b..dd02d3983695 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_init.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_init.c @@ -87,6 +87,8 @@ static const struct hwseq_private_funcs dcn10_private_funcs = { .reset_hw_ctx_wrap = dcn10_reset_hw_ctx_wrap, .enable_stream_timing = dcn10_enable_stream_timing, .edp_backlight_control = dce110_edp_backlight_control, + .is_panel_backlight_on = dce110_is_panel_backlight_on, + .is_panel_powered_on = dce110_is_panel_powered_on, .disable_stream_gating = NULL, .enable_stream_gating = NULL, .setup_vupdate_interrupt = dcn10_setup_vupdate_interrupt, diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_init.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_init.c index 44ec5f5f9fd2..6c4f90f58656 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_init.c +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_init.c @@ -97,6 +97,8 @@ static const struct hwseq_private_funcs dcn20_private_funcs = { .reset_hw_ctx_wrap = dcn20_reset_hw_ctx_wrap, .enable_stream_timing = dcn20_enable_stream_timing, .edp_backlight_control = dce110_edp_backlight_control, + .is_panel_backlight_on = dce110_is_panel_backlight_on, + .is_panel_powered_on = dce110_is_panel_powered_on, .disable_stream_gating = dcn20_disable_stream_gating, .enable_stream_gating = dcn20_enable_stream_gating, .setup_vupdate_interrupt = dcn20_setup_vupdate_interrupt, diff --git a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_init.c b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_init.c index 53006f3b9eb9..f9a7e43d66b9 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_init.c +++ b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_init.c @@ -105,6 +105,8 @@ static const struct hwseq_private_funcs dcn21_private_funcs = { .reset_hw_ctx_wrap = dcn20_reset_hw_ctx_wrap, .enable_stream_timing = dcn20_enable_stream_timing, .edp_backlight_control = dce110_edp_backlight_control, + .is_panel_backlight_on = dce110_is_panel_backlight_on, + .is_panel_powered_on = dce110_is_panel_powered_on, .disable_stream_gating = dcn20_disable_stream_gating, .enable_stream_gating = dcn20_enable_stream_gating, .setup_vupdate_interrupt = dcn20_setup_vupdate_interrupt, diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer_private.h b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer_private.h index ecf566378ccd..c5511e6157af 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer_private.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer_private.h @@ -97,6 +97,8 @@ struct hwseq_private_funcs { struct dc *dc); void (*edp_backlight_control)(struct dc_link *link, bool enable); + bool (*is_panel_backlight_on)(struct dc_link *link); + bool (*is_panel_powered_on)(struct dc_link *link); void (*setup_vupdate_interrupt)(struct dc *dc, struct pipe_ctx *pipe_ctx); bool (*did_underflow_occur)(struct dc *dc, struct pipe_ctx *pipe_ctx); -- cgit From c01760d6616d832df3e0b5df4837a9aebe510348 Mon Sep 17 00:00:00 2001 From: Anthony Koo Date: Wed, 5 Feb 2020 21:01:56 -0500 Subject: drm/amd/display: make some rn_clk_mgr structs and funcs static [Why] There are some structures and functions meant only to be used in the scope of that single rn_clk_mgr c file. [How] Make structs and funcs static if only meant to be used within rn_clk_mgr Signed-off-by: Anthony Koo Reviewed-by: Aric Cyr Acked-by: Rodrigo Siqueira Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/gpu/drm/amd/display') diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c index 5d82ec1f1ce5..64cbd5462c79 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c @@ -405,7 +405,7 @@ void rn_init_clocks(struct clk_mgr *clk_mgr) clk_mgr->clks.pwr_state = DCN_PWR_STATE_UNKNOWN; } -void build_watermark_ranges(struct clk_bw_params *bw_params, struct pp_smu_wm_range_sets *ranges) +static void build_watermark_ranges(struct clk_bw_params *bw_params, struct pp_smu_wm_range_sets *ranges) { int i, num_valid_sets; @@ -503,7 +503,7 @@ static struct clk_mgr_funcs dcn21_funcs = { .notify_wm_ranges = rn_notify_wm_ranges }; -struct clk_bw_params rn_bw_params = { +static struct clk_bw_params rn_bw_params = { .vram_type = Ddr4MemType, .num_channels = 1, .clk_table = { @@ -543,7 +543,7 @@ struct clk_bw_params rn_bw_params = { }; -struct wm_table ddr4_wm_table = { +static struct wm_table ddr4_wm_table = { .entries = { { .wm_inst = WM_A, @@ -580,7 +580,7 @@ struct wm_table ddr4_wm_table = { } }; -struct wm_table lpddr4_wm_table = { +static struct wm_table lpddr4_wm_table = { .entries = { { .wm_inst = WM_A, -- cgit From c11e57f0506b0a0335976f8165abd2684480ff0a Mon Sep 17 00:00:00 2001 From: Vladimir Stempen Date: Mon, 27 Jan 2020 13:07:45 -0500 Subject: drm/amd/display: programming last delta in output transfer function LUT to a correct value [Why] Currently DAL programs negative slope for the last point of output transfer function curve. [How] Applying a check for the last PWL point for RGB values not to be smaller than previous. If smaller, initialize the last point values to a sum of previous PWL value and previous PWL delta; Signed-off-by: Vladimir Stempen Reviewed-by: Tony Cheng Acked-by: Jun Lei Acked-by: Rodrigo Siqueira Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_cm_common.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'drivers/gpu/drm/amd/display') diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_cm_common.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_cm_common.c index bbd6e01b3eca..47a39eb9400b 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_cm_common.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_cm_common.c @@ -316,6 +316,7 @@ bool cm_helper_translate_curve_to_hw_format( struct pwl_result_data *rgb_resulted; struct pwl_result_data *rgb; struct pwl_result_data *rgb_plus_1; + struct pwl_result_data *rgb_minus_1; int32_t region_start, region_end; int32_t i; @@ -465,9 +466,20 @@ bool cm_helper_translate_curve_to_hw_format( rgb = rgb_resulted; rgb_plus_1 = rgb_resulted + 1; + rgb_minus_1 = rgb; i = 1; while (i != hw_points + 1) { + + if (i >= hw_points - 1) { + if (dc_fixpt_lt(rgb_plus_1->red, rgb->red)) + rgb_plus_1->red = dc_fixpt_add(rgb->red, rgb_minus_1->delta_red); + if (dc_fixpt_lt(rgb_plus_1->green, rgb->green)) + rgb_plus_1->green = dc_fixpt_add(rgb->green, rgb_minus_1->delta_green); + if (dc_fixpt_lt(rgb_plus_1->blue, rgb->blue)) + rgb_plus_1->blue = dc_fixpt_add(rgb->blue, rgb_minus_1->delta_blue); + } + rgb->delta_red = dc_fixpt_sub(rgb_plus_1->red, rgb->red); rgb->delta_green = dc_fixpt_sub(rgb_plus_1->green, rgb->green); rgb->delta_blue = dc_fixpt_sub(rgb_plus_1->blue, rgb->blue); @@ -482,6 +494,7 @@ bool cm_helper_translate_curve_to_hw_format( } ++rgb_plus_1; + rgb_minus_1 = rgb; ++rgb; ++i; } -- cgit From 2364076772b11c1ab07fdb62cae4222999c9217f Mon Sep 17 00:00:00 2001 From: Nicholas Kazlauskas Date: Tue, 11 Feb 2020 09:48:18 -0500 Subject: drm/amd/display: Add DMUB firmware state debugfs [Why] Firmware state helps to debug sequence issues and hangs for DMCUB commands and we don't have an easy mechanism to dump it from the driver. [How] Add a debugfs entry to dump the current firmware state. Example usage: cat /sys/kernel/debug/dri/0/amdgpu_dm_dmub_fw_state Signed-off-by: Nicholas Kazlauskas Reviewed-by: Hersen Wu Acked-by: Rodrigo Siqueira Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c | 27 ++++++++++++++++++++++ 1 file changed, 27 insertions(+) (limited to 'drivers/gpu/drm/amd/display') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c index ead5c05eec92..8ec3b4335c69 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c @@ -732,6 +732,29 @@ static int dmub_tracebuffer_show(struct seq_file *m, void *data) return 0; } +/** + * Returns the DMCUB firmware state contents. + * Example usage: cat /sys/kernel/debug/dri/0/amdgpu_dm_dmub_fw_state + */ +static int dmub_fw_state_show(struct seq_file *m, void *data) +{ + struct amdgpu_device *adev = m->private; + struct dmub_srv_fb_info *fb_info = adev->dm.dmub_fb_info; + uint8_t *state_base; + uint32_t state_size; + + if (!fb_info) + return 0; + + state_base = (uint8_t *)fb_info->fb[DMUB_WINDOW_6_FW_STATE].cpu_addr; + if (!state_base) + return 0; + + state_size = fb_info->fb[DMUB_WINDOW_6_FW_STATE].size; + + return seq_write(m, state_base, state_size); +} + /* * Returns the current and maximum output bpc for the connector. * Example usage: cat /sys/kernel/debug/dri/0/DP-1/output_bpc @@ -937,6 +960,7 @@ static ssize_t dp_dpcd_data_read(struct file *f, char __user *buf, return read_size - r; } +DEFINE_SHOW_ATTRIBUTE(dmub_fw_state); DEFINE_SHOW_ATTRIBUTE(dmub_tracebuffer); DEFINE_SHOW_ATTRIBUTE(output_bpc); DEFINE_SHOW_ATTRIBUTE(vrr_range); @@ -1249,5 +1273,8 @@ int dtn_debugfs_init(struct amdgpu_device *adev) debugfs_create_file_unsafe("amdgpu_dm_dmub_tracebuffer", 0644, root, adev, &dmub_tracebuffer_fops); + debugfs_create_file_unsafe("amdgpu_dm_dmub_fw_state", 0644, root, + adev, &dmub_fw_state_fops); + return 0; } -- cgit From 31cf6f35934757a6dc752e724ca529a116451b4d Mon Sep 17 00:00:00 2001 From: Sung Lee Date: Wed, 12 Feb 2020 10:29:48 -0500 Subject: drm/amd/display: Revert "DCN2.x Do not program DPPCLK if same value" [WHY] Not programming dto with same values causes test failures in DCN2 diags DPP tests. [HOW] This reverts commit 1b53e733238c0f7faa4744ec7c8c6f193649f168. Signed-off-by: Sung Lee Reviewed-by: Yongqiang Sun Acked-by: Rodrigo Siqueira Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/clk_mgr/dcn20/dcn20_clk_mgr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu/drm/amd/display') diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn20/dcn20_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn20/dcn20_clk_mgr.c index 68a1120ff674..368d497bc64b 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn20/dcn20_clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn20/dcn20_clk_mgr.c @@ -117,7 +117,7 @@ void dcn20_update_clocks_update_dpp_dto(struct clk_mgr_internal *clk_mgr, prev_dppclk_khz = clk_mgr->base.ctx->dc->current_state->res_ctx.pipe_ctx[i].plane_res.bw.dppclk_khz; - if ((prev_dppclk_khz > dppclk_khz && safe_to_lower) || prev_dppclk_khz < dppclk_khz) { + if (safe_to_lower || prev_dppclk_khz < dppclk_khz) { clk_mgr->dccg->funcs->update_dpp_dto( clk_mgr->dccg, dpp_inst, dppclk_khz); } -- cgit From b01f22ec88103d781f27aadb29277a35302db083 Mon Sep 17 00:00:00 2001 From: David Galiffi Date: Wed, 29 Jan 2020 17:02:32 -0500 Subject: drm/amd/display: Workaround required for link training reliability [Why] A software workaround is required for all vendor-built cards on platform. [How] When performing DP link training, we must send TPS1 before DPCD:100h is written with the proper bit rate value. This change must be applies in ALL cases when LT happens. Signed-off-by: David Galiffi Reviewed-by: Tony Cheng Acked-by: Rodrigo Siqueira Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c | 19 ++++++++++++++++++- drivers/gpu/drm/amd/display/dc/dc_link.h | 1 + 2 files changed, 19 insertions(+), 1 deletion(-) (limited to 'drivers/gpu/drm/amd/display') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c index c0fcee4b5b69..8de9d6f9a477 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c @@ -945,6 +945,17 @@ static enum link_training_result perform_channel_equalization_sequence( } #define TRAINING_AUX_RD_INTERVAL 100 //us +static void start_clock_recovery_pattern_early(struct dc_link *link, + struct link_training_settings *lt_settings, + uint32_t offset) +{ + DC_LOG_HW_LINK_TRAINING("%s\n GPU sends TPS1. Wait 400us.\n", + __func__); + dp_set_hw_training_pattern(link, DP_TRAINING_PATTERN_SEQUENCE_1, offset); + dp_set_hw_lane_settings(link, lt_settings, offset); + udelay(400); +} + static enum link_training_result perform_clock_recovery_sequence( struct dc_link *link, struct link_training_settings *lt_settings, @@ -962,7 +973,8 @@ static enum link_training_result perform_clock_recovery_sequence( retries_cr = 0; retry_count = 0; - dp_set_hw_training_pattern(link, tr_pattern, offset); + if (!link->wa_flags.dp_early_cr_pattern) + dp_set_hw_training_pattern(link, tr_pattern, offset); /* najeeb - The synaptics MST hub can put the LT in * infinite loop by switching the VS @@ -1434,6 +1446,9 @@ enum link_training_result dc_link_dp_perform_link_training( &link->preferred_training_settings, <_settings); + if (link->wa_flags.dp_early_cr_pattern) + start_clock_recovery_pattern_early(link, <_settings, DPRX); + /* 1. set link rate, lane count and spread. */ dpcd_set_link_settings(link, <_settings); @@ -1654,6 +1669,8 @@ enum link_training_result dc_link_dp_sync_lt_attempt( dp_set_panel_mode(link, panel_mode); /* Attempt to train with given link training settings */ + if (link->wa_flags.dp_early_cr_pattern) + start_clock_recovery_pattern_early(link, <_settings, DPRX); /* Set link rate, lane count and spread. */ dpcd_set_link_settings(link, <_settings); diff --git a/drivers/gpu/drm/amd/display/dc/dc_link.h b/drivers/gpu/drm/amd/display/dc/dc_link.h index 5f341e960506..6344de3ca979 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_link.h +++ b/drivers/gpu/drm/amd/display/dc/dc_link.h @@ -135,6 +135,7 @@ struct dc_link { bool dp_keep_receiver_powered; bool dp_skip_DID2; bool dp_skip_reset_segment; + bool dp_early_cr_pattern; } wa_flags; struct link_mst_stream_allocation_table mst_stream_alloc_table; -- cgit From dc326f61c51df641fbf4f42303e860f53ea163c1 Mon Sep 17 00:00:00 2001 From: Jaehyun Chung Date: Tue, 11 Feb 2020 11:19:41 -0500 Subject: drm/amd/display: Monitor patch to delay setting ignore MSA bit [Why] Some displays clear ignore MSA bit on mode change, which cause blackscreen when programming variable vtotals. Ignore MSA bit needs programming needs to be delayed or re-set to be retained. [How] Create patch to delay programming ignore MSA bit after unblanking stream. Signed-off-by: Jaehyun Chung Reviewed-by: Aric Cyr Acked-by: Anthony Koo Acked-by: Rodrigo Siqueira Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 3 +++ drivers/gpu/drm/amd/display/dc/dc_types.h | 1 + 2 files changed, 4 insertions(+) (limited to 'drivers/gpu/drm/amd/display') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index a3bfa05c545e..3420d098d771 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -3095,6 +3095,9 @@ void core_link_enable_stream( dc->hwss.unblank_stream(pipe_ctx, &pipe_ctx->stream->link->cur_link_settings); + if (stream->link->local_sink->edid_caps.panel_patch.delay_ignore_msa > 0) + msleep(stream->link->local_sink->edid_caps.panel_patch.delay_ignore_msa); + if (dc_is_dp_signal(pipe_ctx->stream->signal)) enable_stream_features(pipe_ctx); #if defined(CONFIG_DRM_AMD_DC_HDCP) diff --git a/drivers/gpu/drm/amd/display/dc/dc_types.h b/drivers/gpu/drm/amd/display/dc/dc_types.h index 1490732a4b44..299f6e00f576 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_types.h @@ -230,6 +230,7 @@ struct dc_panel_patch { unsigned int extra_delay_backlight_off; unsigned int extra_t7_ms; unsigned int skip_scdc_overwrite; + unsigned int delay_ignore_msa; }; struct dc_edid_caps { -- cgit From 82054678aeb66907acd63df7d1d5f9556e29a5cc Mon Sep 17 00:00:00 2001 From: Martin Leung Date: Wed, 12 Feb 2020 15:38:51 -0500 Subject: drm/amd/display: Link training TPS1 workaround [Why] Previously implemented early_cr_pattern was link level but the whole asic should be affected. [How] - change old link flag to dc level - new bit in dc->work_arounds set by DM Signed-off-by: Martin Leung Reviewed-by: Joshua Aberback Acked-by: Rodrigo Siqueira Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c | 18 +++++++++--------- drivers/gpu/drm/amd/display/dc/dc.h | 1 + drivers/gpu/drm/amd/display/dc/dc_link.h | 1 - 3 files changed, 10 insertions(+), 10 deletions(-) (limited to 'drivers/gpu/drm/amd/display') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c index 8de9d6f9a477..93127bc90f3c 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c @@ -973,7 +973,7 @@ static enum link_training_result perform_clock_recovery_sequence( retries_cr = 0; retry_count = 0; - if (!link->wa_flags.dp_early_cr_pattern) + if (!link->ctx->dc->work_arounds.lt_early_cr_pattern) dp_set_hw_training_pattern(link, tr_pattern, offset); /* najeeb - The synaptics MST hub can put the LT in @@ -1446,11 +1446,11 @@ enum link_training_result dc_link_dp_perform_link_training( &link->preferred_training_settings, <_settings); - if (link->wa_flags.dp_early_cr_pattern) - start_clock_recovery_pattern_early(link, <_settings, DPRX); - /* 1. set link rate, lane count and spread. */ - dpcd_set_link_settings(link, <_settings); + if (link->ctx->dc->work_arounds.lt_early_cr_pattern) + start_clock_recovery_pattern_early(link, <_settings, DPRX); + else + dpcd_set_link_settings(link, <_settings); if (link->preferred_training_settings.fec_enable != NULL) fec_enable = *link->preferred_training_settings.fec_enable; @@ -1669,11 +1669,11 @@ enum link_training_result dc_link_dp_sync_lt_attempt( dp_set_panel_mode(link, panel_mode); /* Attempt to train with given link training settings */ - if (link->wa_flags.dp_early_cr_pattern) - start_clock_recovery_pattern_early(link, <_settings, DPRX); - /* Set link rate, lane count and spread. */ - dpcd_set_link_settings(link, <_settings); + if (link->ctx->dc->work_arounds.lt_early_cr_pattern) + start_clock_recovery_pattern_early(link, <_settings, DPRX); + else + dpcd_set_link_settings(link, <_settings); /* 2. perform link training (set link training done * to false is done as well) diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index b3f6311d3564..72298520a303 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -126,6 +126,7 @@ struct dc_bug_wa { bool no_connect_phy_config; bool dedcn20_305_wa; bool skip_clock_update; + bool lt_early_cr_pattern; }; struct dc_dcc_surface_param { diff --git a/drivers/gpu/drm/amd/display/dc/dc_link.h b/drivers/gpu/drm/amd/display/dc/dc_link.h index 6344de3ca979..5f341e960506 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_link.h +++ b/drivers/gpu/drm/amd/display/dc/dc_link.h @@ -135,7 +135,6 @@ struct dc_link { bool dp_keep_receiver_powered; bool dp_skip_DID2; bool dp_skip_reset_segment; - bool dp_early_cr_pattern; } wa_flags; struct link_mst_stream_allocation_table mst_stream_alloc_table; -- cgit From 3ebf1468ccf8ea37929fa8b123a7b7218a49f484 Mon Sep 17 00:00:00 2001 From: Peikang Zhang Date: Thu, 13 Feb 2020 16:05:23 -0500 Subject: drm/amd/display: Add visual confirm support for FreeSync 2 ARGB2101010 [Why] DalMPVisualConfirm does not support FreeSync 2 ARGB2101010 which causes black visual confirm bar when playing HDR video on FreeSync 2 display in full screen mode [How] Added pink color for DalMPVisualConfirm on FreeSync 2 ARGB2101010 surface Signed-off-by: Peikang Zhang Reviewed-by: Anthony Koo Acked-by: Rodrigo Siqueira Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers/gpu/drm/amd/display') diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 53083e658fe0..200510859e25 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -2121,6 +2121,10 @@ void dcn10_get_hdr_visual_confirm_color( if (top_pipe_ctx->stream->out_transfer_func->tf == TRANSFER_FUNCTION_PQ) { /* HDR10, ARGB2101010 - set boarder color to red */ color->color_r_cr = color_value; + } else if (top_pipe_ctx->stream->out_transfer_func->tf == TRANSFER_FUNCTION_GAMMA22) { + /* FreeSync 2 ARGB2101010 - set boarder color to pink */ + color->color_r_cr = color_value; + color->color_b_cb = color_value; } break; case PIXEL_FORMAT_FP16: -- cgit From 56260cbff87dd27b33c33c50b18a056f6b8e3ba2 Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Wed, 11 Dec 2019 15:16:28 -0500 Subject: drm/amd/display: update dml input population function Update dcn20_populate_dml_pipes_from_context to correctly handle odm when no surface is provided. Signed-off-by: Dmytro Laktyushkin Reviewed-by: Jun Lei Acked-by: Rodrigo Siqueira Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/dcn20/dcn20_resource.c | 26 ++++++++++++++-------- .../drm/amd/display/dc/dml/display_mode_structs.h | 1 + .../gpu/drm/amd/display/dc/dml/display_mode_vba.c | 2 -- .../gpu/drm/amd/display/dc/dml/display_mode_vba.h | 3 --- 4 files changed, 18 insertions(+), 14 deletions(-) (limited to 'drivers/gpu/drm/amd/display') diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c index 080d4581a93d..883ecd2ed4c8 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c @@ -1949,9 +1949,14 @@ int dcn20_populate_dml_pipes_from_context( } pipes[pipe_cnt].pipe.src.hsplit_grp = res_ctx->pipe_ctx[i].pipe_idx; if (res_ctx->pipe_ctx[i].top_pipe && res_ctx->pipe_ctx[i].top_pipe->plane_state - == res_ctx->pipe_ctx[i].plane_state) - pipes[pipe_cnt].pipe.src.hsplit_grp = res_ctx->pipe_ctx[i].top_pipe->pipe_idx; - else if (res_ctx->pipe_ctx[i].prev_odm_pipe) { + == res_ctx->pipe_ctx[i].plane_state) { + struct pipe_ctx *first_pipe = res_ctx->pipe_ctx[i].top_pipe; + + while (first_pipe->top_pipe && first_pipe->top_pipe->plane_state + == res_ctx->pipe_ctx[i].plane_state) + first_pipe = first_pipe->top_pipe; + pipes[pipe_cnt].pipe.src.hsplit_grp = first_pipe->pipe_idx; + } else if (res_ctx->pipe_ctx[i].prev_odm_pipe) { struct pipe_ctx *first_pipe = res_ctx->pipe_ctx[i].prev_odm_pipe; while (first_pipe->prev_odm_pipe) @@ -2046,6 +2051,7 @@ int dcn20_populate_dml_pipes_from_context( pipes[pipe_cnt].pipe.src.cur1_bpp = dm_cur_32bit; if (!res_ctx->pipe_ctx[i].plane_state) { + pipes[pipe_cnt].pipe.src.is_hsplit = pipes[pipe_cnt].pipe.dest.odm_combine != dm_odm_combine_mode_disabled; pipes[pipe_cnt].pipe.src.source_scan = dm_horz; pipes[pipe_cnt].pipe.src.sw_mode = dm_sw_linear; pipes[pipe_cnt].pipe.src.macro_tile_size = dm_64k_tile; @@ -2071,19 +2077,21 @@ int dcn20_populate_dml_pipes_from_context( pipes[pipe_cnt].pipe.scale_ratio_depth.scl_enable = 0; /*Lb only or Full scl*/ pipes[pipe_cnt].pipe.scale_taps.htaps = 1; pipes[pipe_cnt].pipe.scale_taps.vtaps = 1; - pipes[pipe_cnt].pipe.src.is_hsplit = 0; - pipes[pipe_cnt].pipe.dest.odm_combine = 0; pipes[pipe_cnt].pipe.dest.vtotal_min = v_total; pipes[pipe_cnt].pipe.dest.vtotal_max = v_total; + + if (pipes[pipe_cnt].pipe.dest.odm_combine == dm_odm_combine_mode_2to1) { + pipes[pipe_cnt].pipe.src.viewport_width /= 2; + pipes[pipe_cnt].pipe.dest.recout_width /= 2; + } } else { struct dc_plane_state *pln = res_ctx->pipe_ctx[i].plane_state; struct scaler_data *scl = &res_ctx->pipe_ctx[i].plane_res.scl_data; pipes[pipe_cnt].pipe.src.immediate_flip = pln->flip_immediate; - pipes[pipe_cnt].pipe.src.is_hsplit = (res_ctx->pipe_ctx[i].bottom_pipe - && res_ctx->pipe_ctx[i].bottom_pipe->plane_state == pln) - || (res_ctx->pipe_ctx[i].top_pipe - && res_ctx->pipe_ctx[i].top_pipe->plane_state == pln); + pipes[pipe_cnt].pipe.src.is_hsplit = (res_ctx->pipe_ctx[i].bottom_pipe && res_ctx->pipe_ctx[i].bottom_pipe->plane_state == pln) + || (res_ctx->pipe_ctx[i].top_pipe && res_ctx->pipe_ctx[i].top_pipe->plane_state == pln) + || pipes[pipe_cnt].pipe.dest.odm_combine != dm_odm_combine_mode_disabled; pipes[pipe_cnt].pipe.src.source_scan = pln->rotation == ROTATION_ANGLE_90 || pln->rotation == ROTATION_ANGLE_270 ? dm_vert : dm_horz; pipes[pipe_cnt].pipe.src.viewport_y_y = scl->viewport.y; diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_mode_structs.h b/drivers/gpu/drm/amd/display/dc/dml/display_mode_structs.h index 9bb8bff4cdd9..35fe3c640330 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/display_mode_structs.h +++ b/drivers/gpu/drm/amd/display/dc/dml/display_mode_structs.h @@ -112,6 +112,7 @@ struct _vcs_dpi_soc_bounding_box_st { int use_urgent_burst_bw; unsigned int num_states; struct _vcs_dpi_voltage_scaling_st clock_limits[MAX_CLOCK_LIMIT_STATES]; + double min_dcfclk; bool do_urgent_latency_adjustment; double urgent_latency_adjustment_fabric_clock_component_us; double urgent_latency_adjustment_fabric_clock_reference_mhz; diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.c b/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.c index b3c96d9b472f..e23fa0f05f06 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.c +++ b/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.c @@ -266,8 +266,6 @@ static void fetch_socbb_params(struct display_mode_lib *mode_lib) mode_lib->vba.MaxDispclk[i] = soc->clock_limits[i].dispclk_mhz; mode_lib->vba.DTBCLKPerState[i] = soc->clock_limits[i].dtbclk_mhz; } - mode_lib->vba.MinVoltageLevel = 0; - mode_lib->vba.MaxVoltageLevel = mode_lib->vba.soc.num_states; mode_lib->vba.DoUrgentLatencyAdjustment = soc->do_urgent_latency_adjustment; diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.h b/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.h index 2875efd85467..cb563a429590 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.h +++ b/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.h @@ -842,8 +842,6 @@ struct vba_vars_st { double DCCRateChroma[DC__NUM_DPP__MAX]; double PHYCLKD18PerState[DC__VOLTAGE_STATES + 1]; - int MinVoltageLevel; - int MaxVoltageLevel; bool WritebackSupportInterleaveAndUsingWholeBufferForASingleStream; bool NumberOfHDMIFRLSupport; @@ -880,7 +878,6 @@ struct vba_vars_st { double TotalMetaRowBandwidth[DC__VOLTAGE_STATES + 1][2]; double TotalVActiveCursorBandwidth[DC__VOLTAGE_STATES + 1][2]; double TotalVActivePixelBandwidth[DC__VOLTAGE_STATES + 1][2]; - bool UseMinimumRequiredDCFCLK; double WritebackDelayTime[DC__NUM_DPP__MAX]; unsigned int DCCYIndependentBlock[DC__NUM_DPP__MAX]; unsigned int DCCCIndependentBlock[DC__NUM_DPP__MAX]; -- cgit From 850d15f2ec93001683b68db4e7f39957c78860d8 Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Mon, 16 Dec 2019 17:50:33 -0500 Subject: drm/amd/display: remove unused dml variable Signed-off-by: Dmytro Laktyushkin Reviewed-by: Eric Bernstein Acked-by: Rodrigo Siqueira Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dml/display_mode_structs.h | 1 - drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.c | 1 - drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.h | 1 - 3 files changed, 3 deletions(-) (limited to 'drivers/gpu/drm/amd/display') diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_mode_structs.h b/drivers/gpu/drm/amd/display/dc/dml/display_mode_structs.h index 35fe3c640330..114f861f7f3e 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/display_mode_structs.h +++ b/drivers/gpu/drm/amd/display/dc/dml/display_mode_structs.h @@ -327,7 +327,6 @@ struct _vcs_dpi_display_pipe_dest_params_st { unsigned int vupdate_width; unsigned int vready_offset; unsigned char interlaced; - unsigned char embedded; double pixel_rate_mhz; unsigned char synchronized_vblank_all_planes; unsigned char otg_inst; diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.c b/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.c index e23fa0f05f06..193cc9c6b180 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.c +++ b/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.c @@ -377,7 +377,6 @@ static void fetch_pipe_params(struct display_mode_lib *mode_lib) mode_lib->vba.pipe_plane[j] = mode_lib->vba.NumberOfActivePlanes; - mode_lib->vba.EmbeddedPanel[mode_lib->vba.NumberOfActivePlanes] = dst->embedded; mode_lib->vba.DPPPerPlane[mode_lib->vba.NumberOfActivePlanes] = 1; mode_lib->vba.SourceScan[mode_lib->vba.NumberOfActivePlanes] = (enum scan_direction_class) (src->source_scan); diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.h b/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.h index cb563a429590..5d82fc5a7ed7 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.h +++ b/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.h @@ -389,7 +389,6 @@ struct vba_vars_st { /* vba mode support */ /*inputs*/ - bool EmbeddedPanel[DC__NUM_DPP__MAX]; bool SupportGFX7CompatibleTilingIn32bppAnd64bpp; double MaxHSCLRatio; double MaxVSCLRatio; -- cgit From 7895303b6bcea71d3520171f76a5f0306ef2c65c Mon Sep 17 00:00:00 2001 From: Aric Cyr Date: Tue, 18 Feb 2020 10:29:03 -0500 Subject: drm/amd/display: 3.2.74 Signed-off-by: Aric Cyr Reviewed-by: Aric Cyr Acked-by: Rodrigo Siqueira Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu/drm/amd/display') diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 72298520a303..f8ee2b75d2b8 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -39,7 +39,7 @@ #include "inc/hw/dmcu.h" #include "dml/display_mode_lib.h" -#define DC_VER "3.2.73" +#define DC_VER "3.2.74" #define MAX_SURFACES 3 #define MAX_PLANES 6 -- cgit From 9dac88d8792af034d240c2df148b46e0f9ab00ca Mon Sep 17 00:00:00 2001 From: Wyatt Wood Date: Wed, 12 Feb 2020 15:17:52 -0500 Subject: drm/amd/display: Add driver support for enabling PSR on DMCUB [Why] We want to be able to enable PSR on DMCUB, and fallback to DMCU when necessary. [How] Add infrastructure to enable and disable PSR on DMCUB. Signed-off-by: Wyatt Wood Reviewed-by: Nicholas Kazlauskas Acked-by: Rodrigo Siqueira Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 4 ++-- drivers/gpu/drm/amd/display/dc/dc.h | 1 + drivers/gpu/drm/amd/display/dc/dc_link.h | 1 + drivers/gpu/drm/amd/display/dc/dce/Makefile | 2 +- drivers/gpu/drm/amd/display/dc/dce/dmub_psr.c | 5 +++-- drivers/gpu/drm/amd/display/dc/dce/dmub_psr.h | 3 ++- drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c | 17 +++++++++++++---- drivers/gpu/drm/amd/display/dmub/inc/dmub_gpint_cmd.h | 1 + 8 files changed, 24 insertions(+), 10 deletions(-) (limited to 'drivers/gpu/drm/amd/display') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index 3420d098d771..2ccc2db93f5d 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -45,7 +45,7 @@ #include "dpcd_defs.h" #include "dmcu.h" #include "hw/clk_mgr.h" -#include "../dce/dmub_psr.h" +#include "dce/dmub_psr.h" #define DC_LOGGER_INIT(logger) @@ -2433,7 +2433,7 @@ bool dc_link_set_psr_allow_active(struct dc_link *link, bool allow_active, bool struct dmcu *dmcu = dc->res_pool->dmcu; struct dmub_psr *psr = dc->res_pool->psr; - if ((psr != NULL) && link->psr_feature_enabled) + if (psr != NULL && link->psr_feature_enabled) psr->funcs->psr_enable(psr, allow_active); else if ((dmcu != NULL && dmcu->funcs->is_dmcu_initialized(dmcu)) && link->psr_feature_enabled) dmcu->funcs->set_psr_enable(dmcu, allow_active, wait); diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index f8ee2b75d2b8..e10d5a7d0cb8 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -410,6 +410,7 @@ struct dc_debug_options { bool dmub_offload_enabled; bool dmcub_emulation; bool dmub_command_table; /* for testing only */ + bool psr_on_dmub; struct dc_bw_validation_profile bw_val_profile; bool disable_fec; bool disable_48mhz_pwrdwn; diff --git a/drivers/gpu/drm/amd/display/dc/dc_link.h b/drivers/gpu/drm/amd/display/dc/dc_link.h index 5f341e960506..c45c7680fa58 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_link.h +++ b/drivers/gpu/drm/amd/display/dc/dc_link.h @@ -26,6 +26,7 @@ #ifndef DC_LINK_H_ #define DC_LINK_H_ +#include "dc.h" #include "dc_types.h" #include "grph_object_defs.h" diff --git a/drivers/gpu/drm/amd/display/dc/dce/Makefile b/drivers/gpu/drm/amd/display/dc/dce/Makefile index fdf3d8f87eee..fbfcff700971 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dce/Makefile @@ -29,7 +29,7 @@ DCE = dce_audio.o dce_stream_encoder.o dce_link_encoder.o dce_hwseq.o \ dce_mem_input.o dce_clock_source.o dce_scl_filters.o dce_transform.o \ dce_opp.o dce_dmcu.o dce_abm.o dce_ipp.o dce_aux.o \ -dce_i2c.o dce_i2c_hw.o dce_i2c_sw.o +dce_i2c.o dce_i2c_hw.o dce_i2c_sw.o dmub_psr.o AMD_DAL_DCE = $(addprefix $(AMDDALPATH)/dc/dce/,$(DCE)) diff --git a/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.c b/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.c index 22cd68f7dca0..2c932c29f1f9 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.c @@ -27,7 +27,7 @@ #include "dc.h" #include "dc_dmub_srv.h" #include "../../dmub/inc/dmub_srv.h" -#include "dmub_fw_state.h" +#include "../../dmub/inc/dmub_gpint_cmd.h" #include "core_types.h" #define MAX_PIPES 6 @@ -131,8 +131,9 @@ static bool dmub_psr_copy_settings(struct dmub_psr *dmub, = &cmd.psr_copy_settings.psr_copy_settings_data; struct pipe_ctx *pipe_ctx = NULL; struct resource_context *res_ctx = &link->ctx->dc->current_state->res_ctx; + int i = 0; - for (int i = 0; i < MAX_PIPES; i++) { + for (i = 0; i < MAX_PIPES; i++) { if (res_ctx && res_ctx->pipe_ctx[i].stream && res_ctx->pipe_ctx[i].stream->link && diff --git a/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.h b/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.h index 3de7b9439f42..f404fecd6410 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.h @@ -27,6 +27,7 @@ #define _DMUB_PSR_H_ #include "os_types.h" +#include "dc_link.h" struct dmub_psr { struct dc_context *ctx; @@ -44,4 +45,4 @@ struct dmub_psr *dmub_psr_create(struct dc_context *ctx); void dmub_psr_destroy(struct dmub_psr **dmub); -#endif /* _DCE_DMUB_H_ */ +#endif /* _DMUB_PSR_H_ */ diff --git a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c index e7076b0d7afb..f453de10aa2d 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c @@ -84,7 +84,7 @@ #include "dcn21_resource.h" #include "vm_helper.h" #include "dcn20/dcn20_vmid.h" -#include "../dce/dmub_psr.h" +#include "dce/dmub_psr.h" #define SOC_BOUNDING_BOX_VALID false #define DC_LOGGER_INIT(logger) @@ -995,6 +995,9 @@ static void dcn21_resource_destruct(struct dcn21_resource_pool *pool) if (pool->base.dmcu != NULL) dce_dmcu_destroy(&pool->base.dmcu); + if (pool->base.psr != NULL) + dmub_psr_destroy(&pool->base.psr); + if (pool->base.dccg != NULL) dcn_dccg_destroy(&pool->base.dccg); @@ -1843,9 +1846,15 @@ static bool dcn21_resource_construct( goto create_fail; } - // Leave as NULL to not affect current dmcu psr programming sequence - // Will be uncommented when functionality is confirmed to be working - pool->base.psr = NULL; + if (dc->debug.psr_on_dmub) { + pool->base.psr = dmub_psr_create(ctx); + + if (pool->base.psr == NULL) { + dm_error("DC: failed to create psr obj!\n"); + BREAK_TO_DEBUGGER(); + goto create_fail; + } + } pool->base.abm = dce_abm_create(ctx, &abm_regs, diff --git a/drivers/gpu/drm/amd/display/dmub/inc/dmub_gpint_cmd.h b/drivers/gpu/drm/amd/display/dmub/inc/dmub_gpint_cmd.h index e13685917dab..652d6fc061b6 100644 --- a/drivers/gpu/drm/amd/display/dmub/inc/dmub_gpint_cmd.h +++ b/drivers/gpu/drm/amd/display/dmub/inc/dmub_gpint_cmd.h @@ -63,6 +63,7 @@ enum dmub_gpint_command { DMUB_GPINT__INVALID_COMMAND = 0, DMUB_GPINT__GET_FW_VERSION = 1, DMUB_GPINT__STOP_FW = 2, + DMUB_GPINT__GET_PSR_STATE = 7, }; /** -- cgit From 41ef3dcd86443fab3f0ba50902d13935bc12d24f Mon Sep 17 00:00:00 2001 From: Michael Strauss Date: Thu, 13 Feb 2020 15:08:13 -0500 Subject: drm/amd/display: Fix RV2 Variant Detection [WHY] RV2 and variants are indistinguishable by hw internal rev alone, need to be distinguishable in order to correctly set max vlevel. Previous detection change incorrectly checked for hw internal rev. [HOW] Use pci revision to check if RV2 or low power variant Correct a few overlapping ASICREV range checks Signed-off-by: Michael Strauss Reviewed-by: Michael Strauss Acked-by: Rodrigo Siqueira Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c | 20 +++++++++++++++----- drivers/gpu/drm/amd/display/dc/clk_mgr/clk_mgr.c | 7 ------- drivers/gpu/drm/amd/display/include/dal_asic_id.h | 12 ++++++------ 3 files changed, 21 insertions(+), 18 deletions(-) (limited to 'drivers/gpu/drm/amd/display') diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c index 1a37550731de..f0f07b160152 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c @@ -703,11 +703,19 @@ static void hack_bounding_box(struct dcn_bw_internal_vars *v, } -unsigned int get_highest_allowed_voltage_level(uint32_t hw_internal_rev) +unsigned int get_highest_allowed_voltage_level(uint32_t hw_internal_rev, uint32_t pci_revision_id) { - /* for dali & pollock, the highest voltage level we want is 0 */ - if (ASICREV_IS_POLLOCK(hw_internal_rev) || ASICREV_IS_DALI(hw_internal_rev)) - return 0; + /* for low power RV2 variants, the highest voltage level we want is 0 */ + if (ASICREV_IS_RAVEN2(hw_internal_rev)) + switch (pci_revision_id) { + case PRID_DALI_DE: + case PRID_DALI_DF: + case PRID_DALI_E3: + case PRID_DALI_E4: + return 0; + default: + break; + } /* we are ok with all levels */ return 4; @@ -1277,7 +1285,9 @@ bool dcn_validate_bandwidth( PERFORMANCE_TRACE_END(); BW_VAL_TRACE_FINISH(); - if (bw_limit_pass && v->voltage_level <= get_highest_allowed_voltage_level(dc->ctx->asic_id.hw_internal_rev)) + if (bw_limit_pass && v->voltage_level <= get_highest_allowed_voltage_level( + dc->ctx->asic_id.hw_internal_rev, + dc->ctx->asic_id.pci_revision_id)) return true; else return false; diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/clk_mgr.c index 2f43f1618db8..8ec2dfe45d40 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/clk_mgr.c @@ -153,13 +153,6 @@ struct clk_mgr *dc_clk_mgr_create(struct dc_context *ctx, struct pp_smu_funcs *p #if defined(CONFIG_DRM_AMD_DC_DCN) case FAMILY_RV: - if (ASICREV_IS_DALI(asic_id.hw_internal_rev) || - ASICREV_IS_POLLOCK(asic_id.hw_internal_rev)) { - /* TEMP: this check has to come before ASICREV_IS_RENOIR */ - /* which also incorrectly returns true for Dali/Pollock*/ - rv2_clk_mgr_construct(ctx, clk_mgr, pp_smu); - break; - } if (ASICREV_IS_RENOIR(asic_id.hw_internal_rev)) { rn_clk_mgr_construct(ctx, clk_mgr, pp_smu, dccg); break; diff --git a/drivers/gpu/drm/amd/display/include/dal_asic_id.h b/drivers/gpu/drm/amd/display/include/dal_asic_id.h index a2903985b9e8..ea7015f869c9 100644 --- a/drivers/gpu/drm/amd/display/include/dal_asic_id.h +++ b/drivers/gpu/drm/amd/display/include/dal_asic_id.h @@ -136,8 +136,6 @@ #define RAVEN2_A0 0x81 #define RAVEN2_15D8_REV_94 0x94 #define RAVEN2_15D8_REV_95 0x95 -#define RAVEN2_15D8_REV_E3 0xE3 -#define RAVEN2_15D8_REV_E4 0xE4 #define RAVEN2_15D8_REV_E9 0xE9 #define RAVEN2_15D8_REV_EA 0xEA #define RAVEN2_15D8_REV_EB 0xEB @@ -146,14 +144,16 @@ #ifndef ASICREV_IS_RAVEN #define ASICREV_IS_RAVEN(eChipRev) ((eChipRev >= RAVEN_A0) && eChipRev < RAVEN_UNKNOWN) #endif +#define PRID_DALI_DE 0xDE +#define PRID_DALI_DF 0xDF +#define PRID_DALI_E3 0xE3 +#define PRID_DALI_E4 0xE4 #define ASICREV_IS_PICASSO(eChipRev) ((eChipRev >= PICASSO_A0) && (eChipRev < RAVEN2_A0)) #ifndef ASICREV_IS_RAVEN2 -#define ASICREV_IS_RAVEN2(eChipRev) ((eChipRev >= RAVEN2_A0) && (eChipRev < RAVEN1_F0)) +#define ASICREV_IS_RAVEN2(eChipRev) ((eChipRev >= RAVEN2_A0) && (eChipRev < RENOIR_A0)) #endif #define ASICREV_IS_RV1_F0(eChipRev) ((eChipRev >= RAVEN1_F0) && (eChipRev < RAVEN_UNKNOWN)) -#define ASICREV_IS_DALI(eChipRev) ((eChipRev == RAVEN2_15D8_REV_E3) \ - || (eChipRev == RAVEN2_15D8_REV_E4)) #define ASICREV_IS_POLLOCK(eChipRev) (eChipRev == RAVEN2_15D8_REV_94 \ || eChipRev == RAVEN2_15D8_REV_95 \ || eChipRev == RAVEN2_15D8_REV_E9 \ @@ -177,7 +177,7 @@ enum { #define ASICREV_IS_NAVI14_M(eChipRev) ((eChipRev >= NV_NAVI14_M_A0) && (eChipRev < NV_UNKNOWN)) #define RENOIR_A0 0x91 #define DEVICE_ID_RENOIR_1636 0x1636 // Renoir -#define ASICREV_IS_RENOIR(eChipRev) ((eChipRev >= RENOIR_A0) && (eChipRev < 0xFF)) +#define ASICREV_IS_RENOIR(eChipRev) ((eChipRev >= RENOIR_A0) && (eChipRev < RAVEN1_F0)) /* * ASIC chip ID -- cgit From a18463eff7eb884bb23dbe4d11f018ba6c69fdac Mon Sep 17 00:00:00 2001 From: Alvin Lee Date: Thu, 13 Feb 2020 09:58:36 -0500 Subject: drm/amd/display: Update TTU properly [Why] We need to update TTU properly if DRAMClockChangeWatermark changes. If TTU < DRAMClockChangeWatermark, we pstate won't be allowed and we will hang in some PSR cases. [How] Update TTU if DramClockChangeWatermark value increases (only if TTU was dependent on the watermark value on the DRAMClockChangeWatermark value in the first place). Signed-off-by: Alvin Lee Reviewed-by: Jun Lei Acked-by: Rodrigo Siqueira Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dml/dcn20/display_mode_vba_20v2.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'drivers/gpu/drm/amd/display') diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_mode_vba_20v2.c b/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_mode_vba_20v2.c index 485a9c62ec58..5bbbafacc720 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_mode_vba_20v2.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_mode_vba_20v2.c @@ -2614,6 +2614,14 @@ static void dml20v2_DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndP if (mode_lib->vba.DRAMClockChangeSupportsVActive && mode_lib->vba.MinActiveDRAMClockChangeMargin > 60) { + + for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { + if (mode_lib->vba.PrefetchMode[mode_lib->vba.VoltageLevel][mode_lib->vba.maxMpcComb] == 0) { + if (mode_lib->vba.DRAMClockChangeWatermark > + dml_max(mode_lib->vba.StutterEnterPlusExitWatermark, mode_lib->vba.UrgentWatermark)) + mode_lib->vba.MinTTUVBlank[k] += 25; + } + } mode_lib->vba.DRAMClockChangeWatermark += 25; mode_lib->vba.DRAMClockChangeSupport[0][0] = dm_dram_clock_change_vactive; } else if (mode_lib->vba.DummyPStateCheck && -- cgit From c479912ae67ac4d5a4b6caa00cb7632c14018b26 Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Wed, 11 Dec 2019 11:20:01 -0500 Subject: drm/amd/display: correct dml surface size assignment Need to assign surface size rather than viewport size for surface size dml variable. Signed-off-by: Dmytro Laktyushkin Reviewed-by: Eric Bernstein Acked-by: Rodrigo Siqueira Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/gpu/drm/amd/display') diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.c b/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.c index 193cc9c6b180..6b525c52124c 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.c +++ b/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.c @@ -393,11 +393,11 @@ static void fetch_pipe_params(struct display_mode_lib *mode_lib) mode_lib->vba.ViewportYStartC[mode_lib->vba.NumberOfActivePlanes] = src->viewport_y_c; mode_lib->vba.PitchY[mode_lib->vba.NumberOfActivePlanes] = src->data_pitch; - mode_lib->vba.SurfaceHeightY[mode_lib->vba.NumberOfActivePlanes] = src->viewport_height; - mode_lib->vba.SurfaceWidthY[mode_lib->vba.NumberOfActivePlanes] = src->viewport_width; + mode_lib->vba.SurfaceWidthY[mode_lib->vba.NumberOfActivePlanes] = src->surface_width_y; + mode_lib->vba.SurfaceHeightY[mode_lib->vba.NumberOfActivePlanes] = src->surface_height_y; mode_lib->vba.PitchC[mode_lib->vba.NumberOfActivePlanes] = src->data_pitch_c; - mode_lib->vba.SurfaceHeightC[mode_lib->vba.NumberOfActivePlanes] = src->viewport_height_c; - mode_lib->vba.SurfaceWidthC[mode_lib->vba.NumberOfActivePlanes] = src->viewport_width_c; + mode_lib->vba.SurfaceHeightC[mode_lib->vba.NumberOfActivePlanes] = src->surface_height_c; + mode_lib->vba.SurfaceWidthC[mode_lib->vba.NumberOfActivePlanes] = src->surface_width_c; mode_lib->vba.DCCMetaPitchY[mode_lib->vba.NumberOfActivePlanes] = src->meta_pitch; mode_lib->vba.DCCMetaPitchC[mode_lib->vba.NumberOfActivePlanes] = src->meta_pitch_c; mode_lib->vba.HRatio[mode_lib->vba.NumberOfActivePlanes] = scl->hscl_ratio; -- cgit From 89e94bc57429305e089f149a6e7083e5f36f39c4 Mon Sep 17 00:00:00 2001 From: Yongqiang Sun Date: Fri, 14 Feb 2020 12:55:55 -0500 Subject: drm/amd/display: optimize prgoram wm and clks [Why] In some display configuration like 1080P monitor playing a 1080P video, if user use ALT+F4 to exit Movie and TV, there is a chance clocks are same only water mark changed. Current clock optimization machanism will result in water mark keeps high after exit Movie and TV app. [How] Return if watermark need to be optimized when doing program watermark, perform the optimization after. Signed-off-by: Yongqiang Sun Reviewed-by: Tony Cheng Acked-by: Rodrigo Siqueira Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 10 +- drivers/gpu/drm/amd/display/dc/dc.h | 3 +- .../gpu/drm/amd/display/dc/dcn10/dcn10_hubbub.c | 101 +++++++++++---- .../gpu/drm/amd/display/dc/dcn10/dcn10_hubbub.h | 8 +- .../drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 33 +++-- .../gpu/drm/amd/display/dc/dcn20/dcn20_hubbub.c | 11 +- drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c | 26 ++-- .../gpu/drm/amd/display/dc/dcn21/dcn21_hubbub.c | 137 +++++++++++++++------ .../gpu/drm/amd/display/dc/dcn21/dcn21_hubbub.h | 8 +- drivers/gpu/drm/amd/display/dc/inc/hw/dchubbub.h | 2 +- 10 files changed, 237 insertions(+), 102 deletions(-) (limited to 'drivers/gpu/drm/amd/display') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 7513aa71da38..6dece1ee30bf 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1365,7 +1365,7 @@ bool dc_post_update_surfaces_to_stream(struct dc *dc) int i; struct dc_state *context = dc->current_state; - if (!dc->optimized_required || dc->optimize_seamless_boot_streams > 0) + if ((!dc->clk_optimized_required && !dc->wm_optimized_required) || dc->optimize_seamless_boot_streams > 0) return true; post_surface_trace(dc); @@ -1377,8 +1377,6 @@ bool dc_post_update_surfaces_to_stream(struct dc *dc) dc->hwss.disable_plane(dc, &context->res_ctx.pipe_ctx[i]); } - dc->optimized_required = false; - dc->hwss.optimize_bandwidth(dc, context); return true; } @@ -1826,10 +1824,10 @@ enum surface_update_type dc_check_update_surfaces_for_stream( // If there's an available clock comparator, we use that. if (dc->clk_mgr->funcs->are_clock_states_equal) { if (!dc->clk_mgr->funcs->are_clock_states_equal(&dc->clk_mgr->clks, &dc->current_state->bw_ctx.bw.dcn.clk)) - dc->optimized_required = true; + dc->clk_optimized_required = true; // Else we fallback to mem compare. } else if (memcmp(&dc->current_state->bw_ctx.bw.dcn.clk, &dc->clk_mgr->clks, offsetof(struct dc_clocks, prev_p_state_change_support)) != 0) { - dc->optimized_required = true; + dc->clk_optimized_required = true; } } @@ -2200,7 +2198,7 @@ static void commit_planes_for_stream(struct dc *dc, dc->optimize_seamless_boot_streams--; if (dc->optimize_seamless_boot_streams == 0) - dc->optimized_required = true; + dc->clk_optimized_required = true; } } diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index e10d5a7d0cb8..bc1220dce3b1 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -520,7 +520,8 @@ struct dc { struct dce_hwseq *hwseq; /* Require to optimize clocks and bandwidth for added/removed planes */ - bool optimized_required; + bool clk_optimized_required; + bool wm_optimized_required; /* Require to maintain clocks and bandwidth for UEFI enabled HW */ int optimize_seamless_boot_streams; diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubbub.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubbub.c index 3e851713cf8d..e441c149ff40 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubbub.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubbub.c @@ -243,7 +243,7 @@ void hubbub1_wm_change_req_wa(struct hubbub *hubbub) DCHUBBUB_ARB_WATERMARK_CHANGE_REQUEST, 1); } -void hubbub1_program_urgent_watermarks( +bool hubbub1_program_urgent_watermarks( struct hubbub *hubbub, struct dcn_watermark_set *watermarks, unsigned int refclk_mhz, @@ -251,6 +251,7 @@ void hubbub1_program_urgent_watermarks( { struct dcn10_hubbub *hubbub1 = TO_DCN10_HUBBUB(hubbub); uint32_t prog_wm_value; + bool wm_pending = false; /* Repeat for water mark set A, B, C and D. */ /* clock state A */ @@ -264,7 +265,8 @@ void hubbub1_program_urgent_watermarks( DC_LOG_BANDWIDTH_CALCS("URGENCY_WATERMARK_A calculated =%d\n" "HW register value = 0x%x\n", watermarks->a.urgent_ns, prog_wm_value); - } + } else if (watermarks->a.urgent_ns < hubbub1->watermarks.a.urgent_ns) + wm_pending = true; if (safe_to_lower || watermarks->a.pte_meta_urgent_ns > hubbub1->watermarks.a.pte_meta_urgent_ns) { hubbub1->watermarks.a.pte_meta_urgent_ns = watermarks->a.pte_meta_urgent_ns; @@ -274,7 +276,8 @@ void hubbub1_program_urgent_watermarks( DC_LOG_BANDWIDTH_CALCS("PTE_META_URGENCY_WATERMARK_A calculated =%d\n" "HW register value = 0x%x\n", watermarks->a.pte_meta_urgent_ns, prog_wm_value); - } + } else if (watermarks->a.pte_meta_urgent_ns < hubbub1->watermarks.a.pte_meta_urgent_ns) + wm_pending = true; /* clock state B */ if (safe_to_lower || watermarks->b.urgent_ns > hubbub1->watermarks.b.urgent_ns) { @@ -287,7 +290,8 @@ void hubbub1_program_urgent_watermarks( DC_LOG_BANDWIDTH_CALCS("URGENCY_WATERMARK_B calculated =%d\n" "HW register value = 0x%x\n", watermarks->b.urgent_ns, prog_wm_value); - } + } else if (watermarks->b.urgent_ns < hubbub1->watermarks.b.urgent_ns) + wm_pending = true; if (safe_to_lower || watermarks->b.pte_meta_urgent_ns > hubbub1->watermarks.b.pte_meta_urgent_ns) { hubbub1->watermarks.b.pte_meta_urgent_ns = watermarks->b.pte_meta_urgent_ns; @@ -297,7 +301,8 @@ void hubbub1_program_urgent_watermarks( DC_LOG_BANDWIDTH_CALCS("PTE_META_URGENCY_WATERMARK_B calculated =%d\n" "HW register value = 0x%x\n", watermarks->b.pte_meta_urgent_ns, prog_wm_value); - } + } else if (watermarks->b.pte_meta_urgent_ns < hubbub1->watermarks.b.pte_meta_urgent_ns) + wm_pending = true; /* clock state C */ if (safe_to_lower || watermarks->c.urgent_ns > hubbub1->watermarks.c.urgent_ns) { @@ -310,7 +315,8 @@ void hubbub1_program_urgent_watermarks( DC_LOG_BANDWIDTH_CALCS("URGENCY_WATERMARK_C calculated =%d\n" "HW register value = 0x%x\n", watermarks->c.urgent_ns, prog_wm_value); - } + } else if (watermarks->c.urgent_ns < hubbub1->watermarks.c.urgent_ns) + wm_pending = true; if (safe_to_lower || watermarks->c.pte_meta_urgent_ns > hubbub1->watermarks.c.pte_meta_urgent_ns) { hubbub1->watermarks.c.pte_meta_urgent_ns = watermarks->c.pte_meta_urgent_ns; @@ -320,7 +326,8 @@ void hubbub1_program_urgent_watermarks( DC_LOG_BANDWIDTH_CALCS("PTE_META_URGENCY_WATERMARK_C calculated =%d\n" "HW register value = 0x%x\n", watermarks->c.pte_meta_urgent_ns, prog_wm_value); - } + } else if (watermarks->c.pte_meta_urgent_ns < hubbub1->watermarks.c.pte_meta_urgent_ns) + wm_pending = true; /* clock state D */ if (safe_to_lower || watermarks->d.urgent_ns > hubbub1->watermarks.d.urgent_ns) { @@ -333,7 +340,8 @@ void hubbub1_program_urgent_watermarks( DC_LOG_BANDWIDTH_CALCS("URGENCY_WATERMARK_D calculated =%d\n" "HW register value = 0x%x\n", watermarks->d.urgent_ns, prog_wm_value); - } + } else if (watermarks->d.urgent_ns < hubbub1->watermarks.d.urgent_ns) + wm_pending = true; if (safe_to_lower || watermarks->d.pte_meta_urgent_ns > hubbub1->watermarks.d.pte_meta_urgent_ns) { hubbub1->watermarks.d.pte_meta_urgent_ns = watermarks->d.pte_meta_urgent_ns; @@ -343,10 +351,13 @@ void hubbub1_program_urgent_watermarks( DC_LOG_BANDWIDTH_CALCS("PTE_META_URGENCY_WATERMARK_D calculated =%d\n" "HW register value = 0x%x\n", watermarks->d.pte_meta_urgent_ns, prog_wm_value); - } + } else if (watermarks->d.pte_meta_urgent_ns < hubbub1->watermarks.d.pte_meta_urgent_ns) + wm_pending = true; + + return wm_pending; } -void hubbub1_program_stutter_watermarks( +bool hubbub1_program_stutter_watermarks( struct hubbub *hubbub, struct dcn_watermark_set *watermarks, unsigned int refclk_mhz, @@ -354,6 +365,7 @@ void hubbub1_program_stutter_watermarks( { struct dcn10_hubbub *hubbub1 = TO_DCN10_HUBBUB(hubbub); uint32_t prog_wm_value; + bool wm_pending = false; /* clock state A */ if (safe_to_lower || watermarks->a.cstate_pstate.cstate_enter_plus_exit_ns @@ -368,7 +380,9 @@ void hubbub1_program_stutter_watermarks( DC_LOG_BANDWIDTH_CALCS("SR_ENTER_EXIT_WATERMARK_A calculated =%d\n" "HW register value = 0x%x\n", watermarks->a.cstate_pstate.cstate_enter_plus_exit_ns, prog_wm_value); - } + } else if (watermarks->a.cstate_pstate.cstate_enter_plus_exit_ns + < hubbub1->watermarks.a.cstate_pstate.cstate_enter_plus_exit_ns) + wm_pending = true; if (safe_to_lower || watermarks->a.cstate_pstate.cstate_exit_ns > hubbub1->watermarks.a.cstate_pstate.cstate_exit_ns) { @@ -382,7 +396,9 @@ void hubbub1_program_stutter_watermarks( DC_LOG_BANDWIDTH_CALCS("SR_EXIT_WATERMARK_A calculated =%d\n" "HW register value = 0x%x\n", watermarks->a.cstate_pstate.cstate_exit_ns, prog_wm_value); - } + } else if (watermarks->a.cstate_pstate.cstate_exit_ns + < hubbub1->watermarks.a.cstate_pstate.cstate_exit_ns) + wm_pending = true; /* clock state B */ if (safe_to_lower || watermarks->b.cstate_pstate.cstate_enter_plus_exit_ns @@ -397,7 +413,9 @@ void hubbub1_program_stutter_watermarks( DC_LOG_BANDWIDTH_CALCS("SR_ENTER_EXIT_WATERMARK_B calculated =%d\n" "HW register value = 0x%x\n", watermarks->b.cstate_pstate.cstate_enter_plus_exit_ns, prog_wm_value); - } + } else if (watermarks->b.cstate_pstate.cstate_enter_plus_exit_ns + < hubbub1->watermarks.b.cstate_pstate.cstate_enter_plus_exit_ns) + wm_pending = true; if (safe_to_lower || watermarks->b.cstate_pstate.cstate_exit_ns > hubbub1->watermarks.b.cstate_pstate.cstate_exit_ns) { @@ -411,7 +429,9 @@ void hubbub1_program_stutter_watermarks( DC_LOG_BANDWIDTH_CALCS("SR_EXIT_WATERMARK_B calculated =%d\n" "HW register value = 0x%x\n", watermarks->b.cstate_pstate.cstate_exit_ns, prog_wm_value); - } + } else if (watermarks->b.cstate_pstate.cstate_exit_ns + < hubbub1->watermarks.b.cstate_pstate.cstate_exit_ns) + wm_pending = true; /* clock state C */ if (safe_to_lower || watermarks->c.cstate_pstate.cstate_enter_plus_exit_ns @@ -426,7 +446,9 @@ void hubbub1_program_stutter_watermarks( DC_LOG_BANDWIDTH_CALCS("SR_ENTER_EXIT_WATERMARK_C calculated =%d\n" "HW register value = 0x%x\n", watermarks->c.cstate_pstate.cstate_enter_plus_exit_ns, prog_wm_value); - } + } else if (watermarks->c.cstate_pstate.cstate_enter_plus_exit_ns + < hubbub1->watermarks.c.cstate_pstate.cstate_enter_plus_exit_ns) + wm_pending = true; if (safe_to_lower || watermarks->c.cstate_pstate.cstate_exit_ns > hubbub1->watermarks.c.cstate_pstate.cstate_exit_ns) { @@ -440,7 +462,9 @@ void hubbub1_program_stutter_watermarks( DC_LOG_BANDWIDTH_CALCS("SR_EXIT_WATERMARK_C calculated =%d\n" "HW register value = 0x%x\n", watermarks->c.cstate_pstate.cstate_exit_ns, prog_wm_value); - } + } else if (watermarks->c.cstate_pstate.cstate_exit_ns + < hubbub1->watermarks.c.cstate_pstate.cstate_exit_ns) + wm_pending = true; /* clock state D */ if (safe_to_lower || watermarks->d.cstate_pstate.cstate_enter_plus_exit_ns @@ -455,7 +479,9 @@ void hubbub1_program_stutter_watermarks( DC_LOG_BANDWIDTH_CALCS("SR_ENTER_EXIT_WATERMARK_D calculated =%d\n" "HW register value = 0x%x\n", watermarks->d.cstate_pstate.cstate_enter_plus_exit_ns, prog_wm_value); - } + } else if (watermarks->d.cstate_pstate.cstate_enter_plus_exit_ns + < hubbub1->watermarks.d.cstate_pstate.cstate_enter_plus_exit_ns) + wm_pending = true; if (safe_to_lower || watermarks->d.cstate_pstate.cstate_exit_ns > hubbub1->watermarks.d.cstate_pstate.cstate_exit_ns) { @@ -469,11 +495,14 @@ void hubbub1_program_stutter_watermarks( DC_LOG_BANDWIDTH_CALCS("SR_EXIT_WATERMARK_D calculated =%d\n" "HW register value = 0x%x\n", watermarks->d.cstate_pstate.cstate_exit_ns, prog_wm_value); - } + } else if (watermarks->d.cstate_pstate.cstate_exit_ns + < hubbub1->watermarks.d.cstate_pstate.cstate_exit_ns) + wm_pending = true; + return wm_pending; } -void hubbub1_program_pstate_watermarks( +bool hubbub1_program_pstate_watermarks( struct hubbub *hubbub, struct dcn_watermark_set *watermarks, unsigned int refclk_mhz, @@ -481,6 +510,7 @@ void hubbub1_program_pstate_watermarks( { struct dcn10_hubbub *hubbub1 = TO_DCN10_HUBBUB(hubbub); uint32_t prog_wm_value; + bool wm_pending = false; /* clock state A */ if (safe_to_lower || watermarks->a.cstate_pstate.pstate_change_ns @@ -495,7 +525,9 @@ void hubbub1_program_pstate_watermarks( DC_LOG_BANDWIDTH_CALCS("DRAM_CLK_CHANGE_WATERMARK_A calculated =%d\n" "HW register value = 0x%x\n\n", watermarks->a.cstate_pstate.pstate_change_ns, prog_wm_value); - } + } else if (watermarks->a.cstate_pstate.pstate_change_ns + < hubbub1->watermarks.a.cstate_pstate.pstate_change_ns) + wm_pending = true; /* clock state B */ if (safe_to_lower || watermarks->b.cstate_pstate.pstate_change_ns @@ -510,7 +542,9 @@ void hubbub1_program_pstate_watermarks( DC_LOG_BANDWIDTH_CALCS("DRAM_CLK_CHANGE_WATERMARK_B calculated =%d\n" "HW register value = 0x%x\n\n", watermarks->b.cstate_pstate.pstate_change_ns, prog_wm_value); - } + } else if (watermarks->b.cstate_pstate.pstate_change_ns + < hubbub1->watermarks.b.cstate_pstate.pstate_change_ns) + wm_pending = true; /* clock state C */ if (safe_to_lower || watermarks->c.cstate_pstate.pstate_change_ns @@ -525,7 +559,9 @@ void hubbub1_program_pstate_watermarks( DC_LOG_BANDWIDTH_CALCS("DRAM_CLK_CHANGE_WATERMARK_C calculated =%d\n" "HW register value = 0x%x\n\n", watermarks->c.cstate_pstate.pstate_change_ns, prog_wm_value); - } + } else if (watermarks->c.cstate_pstate.pstate_change_ns + < hubbub1->watermarks.c.cstate_pstate.pstate_change_ns) + wm_pending = true; /* clock state D */ if (safe_to_lower || watermarks->d.cstate_pstate.pstate_change_ns @@ -540,23 +576,33 @@ void hubbub1_program_pstate_watermarks( DC_LOG_BANDWIDTH_CALCS("DRAM_CLK_CHANGE_WATERMARK_D calculated =%d\n" "HW register value = 0x%x\n\n", watermarks->d.cstate_pstate.pstate_change_ns, prog_wm_value); - } + } else if (watermarks->d.cstate_pstate.pstate_change_ns + < hubbub1->watermarks.d.cstate_pstate.pstate_change_ns) + wm_pending = true; + + return wm_pending; } -void hubbub1_program_watermarks( +bool hubbub1_program_watermarks( struct hubbub *hubbub, struct dcn_watermark_set *watermarks, unsigned int refclk_mhz, bool safe_to_lower) { struct dcn10_hubbub *hubbub1 = TO_DCN10_HUBBUB(hubbub); + bool wm_pending = false; /* * Need to clamp to max of the register values (i.e. no wrap) * for dcn1, all wm registers are 21-bit wide */ - hubbub1_program_urgent_watermarks(hubbub, watermarks, refclk_mhz, safe_to_lower); - hubbub1_program_stutter_watermarks(hubbub, watermarks, refclk_mhz, safe_to_lower); - hubbub1_program_pstate_watermarks(hubbub, watermarks, refclk_mhz, safe_to_lower); + if (hubbub1_program_urgent_watermarks(hubbub, watermarks, refclk_mhz, safe_to_lower)) + wm_pending = true; + + if (hubbub1_program_stutter_watermarks(hubbub, watermarks, refclk_mhz, safe_to_lower)) + wm_pending = true; + + if (hubbub1_program_pstate_watermarks(hubbub, watermarks, refclk_mhz, safe_to_lower)) + wm_pending = true; REG_UPDATE(DCHUBBUB_ARB_SAT_LEVEL, DCHUBBUB_ARB_SAT_LEVEL, 60 * refclk_mhz); @@ -570,6 +616,7 @@ void hubbub1_program_watermarks( DCHUBBUB_ARB_WATERMARK_CHANGE_DONE_INTERRUPT_DISABLE, 1, DCHUBBUB_ARB_WATERMARK_CHANGE_REQUEST, 1); #endif + return wm_pending; } void hubbub1_update_dchub( diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubbub.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubbub.h index af57751253de..343a537172c7 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubbub.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubbub.h @@ -308,7 +308,7 @@ bool hubbub1_verify_allow_pstate_change_high( void hubbub1_wm_change_req_wa(struct hubbub *hubbub); -void hubbub1_program_watermarks( +bool hubbub1_program_watermarks( struct hubbub *hubbub, struct dcn_watermark_set *watermarks, unsigned int refclk_mhz, @@ -331,17 +331,17 @@ void hubbub1_construct(struct hubbub *hubbub, const struct dcn_hubbub_shift *hubbub_shift, const struct dcn_hubbub_mask *hubbub_mask); -void hubbub1_program_urgent_watermarks( +bool hubbub1_program_urgent_watermarks( struct hubbub *hubbub, struct dcn_watermark_set *watermarks, unsigned int refclk_mhz, bool safe_to_lower); -void hubbub1_program_stutter_watermarks( +bool hubbub1_program_stutter_watermarks( struct hubbub *hubbub, struct dcn_watermark_set *watermarks, unsigned int refclk_mhz, bool safe_to_lower); -void hubbub1_program_pstate_watermarks( +bool hubbub1_program_pstate_watermarks( struct hubbub *hubbub, struct dcn_watermark_set *watermarks, unsigned int refclk_mhz, diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 200510859e25..8e29403f963a 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -1048,7 +1048,7 @@ void dcn10_plane_atomic_disconnect(struct dc *dc, struct pipe_ctx *pipe_ctx) if (opp != NULL) opp->mpcc_disconnect_pending[pipe_ctx->plane_res.mpcc_inst] = true; - dc->optimized_required = true; + dc->clk_optimized_required = true; if (hubp->funcs->hubp_disconnect) hubp->funcs->hubp_disconnect(hubp); @@ -1099,7 +1099,7 @@ void dcn10_plane_atomic_disable(struct dc *dc, struct pipe_ctx *pipe_ctx) false); hubp->power_gated = true; - dc->optimized_required = false; /* We're powering off, no need to optimize */ + dc->clk_optimized_required = false; /* We're powering off, no need to optimize */ hws->funcs.plane_atomic_power_down(dc, pipe_ctx->plane_res.dpp, @@ -2693,7 +2693,7 @@ void dcn10_prepare_bandwidth( false); } - hubbub->funcs->program_watermarks(hubbub, + dc->wm_optimized_required = hubbub->funcs->program_watermarks(hubbub, &context->bw_ctx.bw.dcn.watermarks, dc->res_pool->ref_clocks.dchub_ref_clock_inKhz / 1000, true); @@ -2717,19 +2717,30 @@ void dcn10_optimize_bandwidth( hws->funcs.verify_allow_pstate_change_high(dc); if (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) { - if (context->stream_count == 0) + if (context->stream_count == 0) { context->bw_ctx.bw.dcn.clk.phyclk_khz = 0; - dc->clk_mgr->funcs->update_clocks( - dc->clk_mgr, - context, + dc->clk_mgr->funcs->update_clocks( + dc->clk_mgr, + context, + true); + } else if (dc->clk_optimized_required || IS_DIAG_DC(dc->ctx->dce_environment)) { + dc->clk_mgr->funcs->update_clocks( + dc->clk_mgr, + context, + true); + } + } + + if (dc->wm_optimized_required || IS_DIAG_DC(dc->ctx->dce_environment)) { + hubbub->funcs->program_watermarks(hubbub, + &context->bw_ctx.bw.dcn.watermarks, + dc->res_pool->ref_clocks.dchub_ref_clock_inKhz / 1000, true); } - hubbub->funcs->program_watermarks(hubbub, - &context->bw_ctx.bw.dcn.watermarks, - dc->res_pool->ref_clocks.dchub_ref_clock_inKhz / 1000, - true); + dc->clk_optimized_required = false; + dc->wm_optimized_required = false; dcn10_stereo_hw_frame_pack_wa(dc, context); if (dc->debug.pplib_wm_report_mode == WM_REPORT_OVERRIDE) diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hubbub.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hubbub.c index 9235f7d29454..c0b21d7450d4 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hubbub.c +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hubbub.c @@ -562,19 +562,23 @@ void hubbub2_get_dchub_ref_freq(struct hubbub *hubbub, } } -static void hubbub2_program_watermarks( +static bool hubbub2_program_watermarks( struct hubbub *hubbub, struct dcn_watermark_set *watermarks, unsigned int refclk_mhz, bool safe_to_lower) { struct dcn20_hubbub *hubbub1 = TO_DCN20_HUBBUB(hubbub); + bool wm_pending = false; /* * Need to clamp to max of the register values (i.e. no wrap) * for dcn1, all wm registers are 21-bit wide */ - hubbub1_program_urgent_watermarks(hubbub, watermarks, refclk_mhz, safe_to_lower); - hubbub1_program_stutter_watermarks(hubbub, watermarks, refclk_mhz, safe_to_lower); + if (hubbub1_program_urgent_watermarks(hubbub, watermarks, refclk_mhz, safe_to_lower)) + wm_pending = true; + + if (hubbub1_program_stutter_watermarks(hubbub, watermarks, refclk_mhz, safe_to_lower)) + wm_pending = true; /* * There's a special case when going from p-state support to p-state unsupported @@ -592,6 +596,7 @@ static void hubbub2_program_watermarks( REG_UPDATE(DCHUBBUB_ARB_DF_REQ_OUTSTAND, DCHUBBUB_ARB_MIN_REQ_OUTSTAND, 180); hubbub->funcs->allow_self_refresh_control(hubbub, !hubbub->ctx->dc->debug.disable_stutter); + return wm_pending; } static const struct hubbub_funcs hubbub2_funcs = { diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c index b9ec40a31f5c..cf13b1db1025 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c @@ -1627,7 +1627,7 @@ void dcn20_prepare_bandwidth( false); /* program dchubbub watermarks */ - hubbub->funcs->program_watermarks(hubbub, + dc->wm_optimized_required = hubbub->funcs->program_watermarks(hubbub, &context->bw_ctx.bw.dcn.watermarks, dc->res_pool->ref_clocks.dchub_ref_clock_inKhz / 1000, false); @@ -1639,16 +1639,22 @@ void dcn20_optimize_bandwidth( { struct hubbub *hubbub = dc->res_pool->hubbub; - /* program dchubbub watermarks */ - hubbub->funcs->program_watermarks(hubbub, - &context->bw_ctx.bw.dcn.watermarks, - dc->res_pool->ref_clocks.dchub_ref_clock_inKhz / 1000, - true); + if (dc->wm_optimized_required || IS_DIAG_DC(dc->ctx->dce_environment)) { + /* program dchubbub watermarks */ + hubbub->funcs->program_watermarks(hubbub, + &context->bw_ctx.bw.dcn.watermarks, + dc->res_pool->ref_clocks.dchub_ref_clock_inKhz / 1000, + true); + dc->wm_optimized_required = false; + } - dc->clk_mgr->funcs->update_clocks( - dc->clk_mgr, - context, - true); + if (dc->clk_optimized_required || IS_DIAG_DC(dc->ctx->dce_environment)) { + dc->clk_mgr->funcs->update_clocks( + dc->clk_mgr, + context, + true); + dc->wm_optimized_required = false; + } } bool dcn20_update_bandwidth( diff --git a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_hubbub.c b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_hubbub.c index f546260c15b7..8440975206e0 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_hubbub.c +++ b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_hubbub.c @@ -141,7 +141,7 @@ int hubbub21_init_dchub(struct hubbub *hubbub, return NUM_VMID; } -void hubbub21_program_urgent_watermarks( +bool hubbub21_program_urgent_watermarks( struct hubbub *hubbub, struct dcn_watermark_set *watermarks, unsigned int refclk_mhz, @@ -149,6 +149,7 @@ void hubbub21_program_urgent_watermarks( { struct dcn20_hubbub *hubbub1 = TO_DCN20_HUBBUB(hubbub); uint32_t prog_wm_value; + bool wm_pending = false; /* Repeat for water mark set A, B, C and D. */ /* clock state A */ @@ -163,7 +164,8 @@ void hubbub21_program_urgent_watermarks( DC_LOG_BANDWIDTH_CALCS("URGENCY_WATERMARK_A calculated =%d\n" "HW register value = 0x%x\n", watermarks->a.urgent_ns, prog_wm_value); - } + } else if (watermarks->a.urgent_ns < hubbub1->watermarks.a.urgent_ns) + wm_pending = true; /* determine the transfer time for a quantity of data for a particular requestor.*/ if (safe_to_lower || watermarks->a.frac_urg_bw_flip @@ -172,7 +174,9 @@ void hubbub21_program_urgent_watermarks( REG_SET(DCHUBBUB_ARB_FRAC_URG_BW_FLIP_A, 0, DCHUBBUB_ARB_FRAC_URG_BW_FLIP_A, watermarks->a.frac_urg_bw_flip); - } + } else if (watermarks->a.frac_urg_bw_flip + < hubbub1->watermarks.a.frac_urg_bw_flip) + wm_pending = true; if (safe_to_lower || watermarks->a.frac_urg_bw_nom > hubbub1->watermarks.a.frac_urg_bw_nom) { @@ -180,14 +184,18 @@ void hubbub21_program_urgent_watermarks( REG_SET(DCHUBBUB_ARB_FRAC_URG_BW_NOM_A, 0, DCHUBBUB_ARB_FRAC_URG_BW_NOM_A, watermarks->a.frac_urg_bw_nom); - } + } else if (watermarks->a.frac_urg_bw_nom + < hubbub1->watermarks.a.frac_urg_bw_nom) + wm_pending = true; + if (safe_to_lower || watermarks->a.urgent_latency_ns > hubbub1->watermarks.a.urgent_latency_ns) { hubbub1->watermarks.a.urgent_latency_ns = watermarks->a.urgent_latency_ns; prog_wm_value = convert_and_clamp(watermarks->a.urgent_latency_ns, refclk_mhz, 0x1fffff); REG_SET(DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_A, 0, DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_A, prog_wm_value); - } + } else if (watermarks->a.urgent_latency_ns < hubbub1->watermarks.a.urgent_latency_ns) + wm_pending = true; /* clock state B */ if (safe_to_lower || watermarks->b.urgent_ns > hubbub1->watermarks.b.urgent_ns) { @@ -201,7 +209,8 @@ void hubbub21_program_urgent_watermarks( DC_LOG_BANDWIDTH_CALCS("URGENCY_WATERMARK_B calculated =%d\n" "HW register value = 0x%x\n", watermarks->b.urgent_ns, prog_wm_value); - } + } else if (watermarks->b.urgent_ns < hubbub1->watermarks.b.urgent_ns) + wm_pending = true; /* determine the transfer time for a quantity of data for a particular requestor.*/ if (safe_to_lower || watermarks->a.frac_urg_bw_flip @@ -210,7 +219,9 @@ void hubbub21_program_urgent_watermarks( REG_SET(DCHUBBUB_ARB_FRAC_URG_BW_FLIP_B, 0, DCHUBBUB_ARB_FRAC_URG_BW_FLIP_B, watermarks->a.frac_urg_bw_flip); - } + } else if (watermarks->a.frac_urg_bw_flip + < hubbub1->watermarks.a.frac_urg_bw_flip) + wm_pending = true; if (safe_to_lower || watermarks->a.frac_urg_bw_nom > hubbub1->watermarks.a.frac_urg_bw_nom) { @@ -218,7 +229,9 @@ void hubbub21_program_urgent_watermarks( REG_SET(DCHUBBUB_ARB_FRAC_URG_BW_NOM_B, 0, DCHUBBUB_ARB_FRAC_URG_BW_NOM_B, watermarks->a.frac_urg_bw_nom); - } + } else if (watermarks->a.frac_urg_bw_nom + < hubbub1->watermarks.a.frac_urg_bw_nom) + wm_pending = true; if (safe_to_lower || watermarks->b.urgent_latency_ns > hubbub1->watermarks.b.urgent_latency_ns) { hubbub1->watermarks.b.urgent_latency_ns = watermarks->b.urgent_latency_ns; @@ -226,7 +239,8 @@ void hubbub21_program_urgent_watermarks( refclk_mhz, 0x1fffff); REG_SET(DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_B, 0, DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_B, prog_wm_value); - } + } else if (watermarks->b.urgent_latency_ns < hubbub1->watermarks.b.urgent_latency_ns) + wm_pending = true; /* clock state C */ if (safe_to_lower || watermarks->c.urgent_ns > hubbub1->watermarks.c.urgent_ns) { @@ -240,7 +254,8 @@ void hubbub21_program_urgent_watermarks( DC_LOG_BANDWIDTH_CALCS("URGENCY_WATERMARK_C calculated =%d\n" "HW register value = 0x%x\n", watermarks->c.urgent_ns, prog_wm_value); - } + } else if (watermarks->c.urgent_ns < hubbub1->watermarks.c.urgent_ns) + wm_pending = true; /* determine the transfer time for a quantity of data for a particular requestor.*/ if (safe_to_lower || watermarks->a.frac_urg_bw_flip @@ -249,7 +264,9 @@ void hubbub21_program_urgent_watermarks( REG_SET(DCHUBBUB_ARB_FRAC_URG_BW_FLIP_C, 0, DCHUBBUB_ARB_FRAC_URG_BW_FLIP_C, watermarks->a.frac_urg_bw_flip); - } + } else if (watermarks->a.frac_urg_bw_flip + < hubbub1->watermarks.a.frac_urg_bw_flip) + wm_pending = true; if (safe_to_lower || watermarks->a.frac_urg_bw_nom > hubbub1->watermarks.a.frac_urg_bw_nom) { @@ -257,7 +274,9 @@ void hubbub21_program_urgent_watermarks( REG_SET(DCHUBBUB_ARB_FRAC_URG_BW_NOM_C, 0, DCHUBBUB_ARB_FRAC_URG_BW_NOM_C, watermarks->a.frac_urg_bw_nom); - } + } else if (watermarks->a.frac_urg_bw_nom + < hubbub1->watermarks.a.frac_urg_bw_nom) + wm_pending = true; if (safe_to_lower || watermarks->c.urgent_latency_ns > hubbub1->watermarks.c.urgent_latency_ns) { hubbub1->watermarks.c.urgent_latency_ns = watermarks->c.urgent_latency_ns; @@ -265,7 +284,8 @@ void hubbub21_program_urgent_watermarks( refclk_mhz, 0x1fffff); REG_SET(DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_C, 0, DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_C, prog_wm_value); - } + } else if (watermarks->c.urgent_latency_ns < hubbub1->watermarks.c.urgent_latency_ns) + wm_pending = true; /* clock state D */ if (safe_to_lower || watermarks->d.urgent_ns > hubbub1->watermarks.d.urgent_ns) { @@ -279,7 +299,8 @@ void hubbub21_program_urgent_watermarks( DC_LOG_BANDWIDTH_CALCS("URGENCY_WATERMARK_D calculated =%d\n" "HW register value = 0x%x\n", watermarks->d.urgent_ns, prog_wm_value); - } + } else if (watermarks->d.urgent_ns < hubbub1->watermarks.d.urgent_ns) + wm_pending = true; /* determine the transfer time for a quantity of data for a particular requestor.*/ if (safe_to_lower || watermarks->a.frac_urg_bw_flip @@ -288,7 +309,9 @@ void hubbub21_program_urgent_watermarks( REG_SET(DCHUBBUB_ARB_FRAC_URG_BW_FLIP_D, 0, DCHUBBUB_ARB_FRAC_URG_BW_FLIP_D, watermarks->a.frac_urg_bw_flip); - } + } else if (watermarks->a.frac_urg_bw_flip + < hubbub1->watermarks.a.frac_urg_bw_flip) + wm_pending = true; if (safe_to_lower || watermarks->a.frac_urg_bw_nom > hubbub1->watermarks.a.frac_urg_bw_nom) { @@ -296,7 +319,9 @@ void hubbub21_program_urgent_watermarks( REG_SET(DCHUBBUB_ARB_FRAC_URG_BW_NOM_D, 0, DCHUBBUB_ARB_FRAC_URG_BW_NOM_D, watermarks->a.frac_urg_bw_nom); - } + } else if (watermarks->a.frac_urg_bw_nom + < hubbub1->watermarks.a.frac_urg_bw_nom) + wm_pending = true; if (safe_to_lower || watermarks->d.urgent_latency_ns > hubbub1->watermarks.d.urgent_latency_ns) { hubbub1->watermarks.d.urgent_latency_ns = watermarks->d.urgent_latency_ns; @@ -304,10 +329,13 @@ void hubbub21_program_urgent_watermarks( refclk_mhz, 0x1fffff); REG_SET(DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_D, 0, DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_D, prog_wm_value); - } + } else if (watermarks->d.urgent_latency_ns < hubbub1->watermarks.d.urgent_latency_ns) + wm_pending = true; + + return wm_pending; } -void hubbub21_program_stutter_watermarks( +bool hubbub21_program_stutter_watermarks( struct hubbub *hubbub, struct dcn_watermark_set *watermarks, unsigned int refclk_mhz, @@ -315,6 +343,7 @@ void hubbub21_program_stutter_watermarks( { struct dcn20_hubbub *hubbub1 = TO_DCN20_HUBBUB(hubbub); uint32_t prog_wm_value; + bool wm_pending = false; /* clock state A */ if (safe_to_lower || watermarks->a.cstate_pstate.cstate_enter_plus_exit_ns @@ -330,7 +359,9 @@ void hubbub21_program_stutter_watermarks( DC_LOG_BANDWIDTH_CALCS("SR_ENTER_EXIT_WATERMARK_A calculated =%d\n" "HW register value = 0x%x\n", watermarks->a.cstate_pstate.cstate_enter_plus_exit_ns, prog_wm_value); - } + } else if (watermarks->a.cstate_pstate.cstate_enter_plus_exit_ns + < hubbub1->watermarks.a.cstate_pstate.cstate_enter_plus_exit_ns) + wm_pending = true; if (safe_to_lower || watermarks->a.cstate_pstate.cstate_exit_ns > hubbub1->watermarks.a.cstate_pstate.cstate_exit_ns) { @@ -345,7 +376,9 @@ void hubbub21_program_stutter_watermarks( DC_LOG_BANDWIDTH_CALCS("SR_EXIT_WATERMARK_A calculated =%d\n" "HW register value = 0x%x\n", watermarks->a.cstate_pstate.cstate_exit_ns, prog_wm_value); - } + } else if (watermarks->a.cstate_pstate.cstate_exit_ns + < hubbub1->watermarks.a.cstate_pstate.cstate_exit_ns) + wm_pending = true; /* clock state B */ if (safe_to_lower || watermarks->b.cstate_pstate.cstate_enter_plus_exit_ns @@ -361,7 +394,9 @@ void hubbub21_program_stutter_watermarks( DC_LOG_BANDWIDTH_CALCS("SR_ENTER_EXIT_WATERMARK_B calculated =%d\n" "HW register value = 0x%x\n", watermarks->b.cstate_pstate.cstate_enter_plus_exit_ns, prog_wm_value); - } + } else if (watermarks->b.cstate_pstate.cstate_enter_plus_exit_ns + < hubbub1->watermarks.b.cstate_pstate.cstate_enter_plus_exit_ns) + wm_pending = true; if (safe_to_lower || watermarks->b.cstate_pstate.cstate_exit_ns > hubbub1->watermarks.b.cstate_pstate.cstate_exit_ns) { @@ -376,7 +411,9 @@ void hubbub21_program_stutter_watermarks( DC_LOG_BANDWIDTH_CALCS("SR_EXIT_WATERMARK_B calculated =%d\n" "HW register value = 0x%x\n", watermarks->b.cstate_pstate.cstate_exit_ns, prog_wm_value); - } + } else if (watermarks->b.cstate_pstate.cstate_exit_ns + < hubbub1->watermarks.b.cstate_pstate.cstate_exit_ns) + wm_pending = true; /* clock state C */ if (safe_to_lower || watermarks->c.cstate_pstate.cstate_enter_plus_exit_ns @@ -392,7 +429,9 @@ void hubbub21_program_stutter_watermarks( DC_LOG_BANDWIDTH_CALCS("SR_ENTER_EXIT_WATERMARK_C calculated =%d\n" "HW register value = 0x%x\n", watermarks->c.cstate_pstate.cstate_enter_plus_exit_ns, prog_wm_value); - } + } else if (watermarks->c.cstate_pstate.cstate_enter_plus_exit_ns + < hubbub1->watermarks.c.cstate_pstate.cstate_enter_plus_exit_ns) + wm_pending = true; if (safe_to_lower || watermarks->c.cstate_pstate.cstate_exit_ns > hubbub1->watermarks.c.cstate_pstate.cstate_exit_ns) { @@ -407,7 +446,9 @@ void hubbub21_program_stutter_watermarks( DC_LOG_BANDWIDTH_CALCS("SR_EXIT_WATERMARK_C calculated =%d\n" "HW register value = 0x%x\n", watermarks->c.cstate_pstate.cstate_exit_ns, prog_wm_value); - } + } else if (watermarks->c.cstate_pstate.cstate_exit_ns + < hubbub1->watermarks.c.cstate_pstate.cstate_exit_ns) + wm_pending = true; /* clock state D */ if (safe_to_lower || watermarks->d.cstate_pstate.cstate_enter_plus_exit_ns @@ -423,7 +464,9 @@ void hubbub21_program_stutter_watermarks( DC_LOG_BANDWIDTH_CALCS("SR_ENTER_EXIT_WATERMARK_D calculated =%d\n" "HW register value = 0x%x\n", watermarks->d.cstate_pstate.cstate_enter_plus_exit_ns, prog_wm_value); - } + } else if (watermarks->d.cstate_pstate.cstate_enter_plus_exit_ns + < hubbub1->watermarks.d.cstate_pstate.cstate_enter_plus_exit_ns) + wm_pending = true; if (safe_to_lower || watermarks->d.cstate_pstate.cstate_exit_ns > hubbub1->watermarks.d.cstate_pstate.cstate_exit_ns) { @@ -438,10 +481,14 @@ void hubbub21_program_stutter_watermarks( DC_LOG_BANDWIDTH_CALCS("SR_EXIT_WATERMARK_D calculated =%d\n" "HW register value = 0x%x\n", watermarks->d.cstate_pstate.cstate_exit_ns, prog_wm_value); - } + } else if (watermarks->d.cstate_pstate.cstate_exit_ns + < hubbub1->watermarks.d.cstate_pstate.cstate_exit_ns) + wm_pending = true; + + return wm_pending; } -void hubbub21_program_pstate_watermarks( +bool hubbub21_program_pstate_watermarks( struct hubbub *hubbub, struct dcn_watermark_set *watermarks, unsigned int refclk_mhz, @@ -450,6 +497,8 @@ void hubbub21_program_pstate_watermarks( struct dcn20_hubbub *hubbub1 = TO_DCN20_HUBBUB(hubbub); uint32_t prog_wm_value; + bool wm_pending = false; + /* clock state A */ if (safe_to_lower || watermarks->a.cstate_pstate.pstate_change_ns > hubbub1->watermarks.a.cstate_pstate.pstate_change_ns) { @@ -464,7 +513,9 @@ void hubbub21_program_pstate_watermarks( DC_LOG_BANDWIDTH_CALCS("DRAM_CLK_CHANGE_WATERMARK_A calculated =%d\n" "HW register value = 0x%x\n\n", watermarks->a.cstate_pstate.pstate_change_ns, prog_wm_value); - } + } else if (watermarks->a.cstate_pstate.pstate_change_ns + < hubbub1->watermarks.a.cstate_pstate.pstate_change_ns) + wm_pending = true; /* clock state B */ if (safe_to_lower || watermarks->b.cstate_pstate.pstate_change_ns @@ -480,7 +531,9 @@ void hubbub21_program_pstate_watermarks( DC_LOG_BANDWIDTH_CALCS("DRAM_CLK_CHANGE_WATERMARK_B calculated =%d\n" "HW register value = 0x%x\n\n", watermarks->b.cstate_pstate.pstate_change_ns, prog_wm_value); - } + } else if (watermarks->b.cstate_pstate.pstate_change_ns + < hubbub1->watermarks.b.cstate_pstate.pstate_change_ns) + wm_pending = false; /* clock state C */ if (safe_to_lower || watermarks->c.cstate_pstate.pstate_change_ns @@ -496,7 +549,9 @@ void hubbub21_program_pstate_watermarks( DC_LOG_BANDWIDTH_CALCS("DRAM_CLK_CHANGE_WATERMARK_C calculated =%d\n" "HW register value = 0x%x\n\n", watermarks->c.cstate_pstate.pstate_change_ns, prog_wm_value); - } + } else if (watermarks->c.cstate_pstate.pstate_change_ns + < hubbub1->watermarks.c.cstate_pstate.pstate_change_ns) + wm_pending = true; /* clock state D */ if (safe_to_lower || watermarks->d.cstate_pstate.pstate_change_ns @@ -512,20 +567,30 @@ void hubbub21_program_pstate_watermarks( DC_LOG_BANDWIDTH_CALCS("DRAM_CLK_CHANGE_WATERMARK_D calculated =%d\n" "HW register value = 0x%x\n\n", watermarks->d.cstate_pstate.pstate_change_ns, prog_wm_value); - } + } else if (watermarks->d.cstate_pstate.pstate_change_ns + < hubbub1->watermarks.d.cstate_pstate.pstate_change_ns) + wm_pending = true; + + return wm_pending; } -void hubbub21_program_watermarks( +bool hubbub21_program_watermarks( struct hubbub *hubbub, struct dcn_watermark_set *watermarks, unsigned int refclk_mhz, bool safe_to_lower) { struct dcn20_hubbub *hubbub1 = TO_DCN20_HUBBUB(hubbub); + bool wm_pending = false; + + if (hubbub21_program_urgent_watermarks(hubbub, watermarks, refclk_mhz, safe_to_lower)) + wm_pending = true; - hubbub21_program_urgent_watermarks(hubbub, watermarks, refclk_mhz, safe_to_lower); - hubbub21_program_stutter_watermarks(hubbub, watermarks, refclk_mhz, safe_to_lower); - hubbub21_program_pstate_watermarks(hubbub, watermarks, refclk_mhz, safe_to_lower); + if (hubbub21_program_stutter_watermarks(hubbub, watermarks, refclk_mhz, safe_to_lower)) + wm_pending = true; + + if (hubbub21_program_pstate_watermarks(hubbub, watermarks, refclk_mhz, safe_to_lower)) + wm_pending = true; /* * The DCHub arbiter has a mechanism to dynamically rate limit the DCHub request stream to the fabric. @@ -549,6 +614,8 @@ void hubbub21_program_watermarks( DCHUBBUB_ARB_MAX_QOS_COMMIT_THRESHOLD, 0xF); hubbub1_allow_self_refresh_control(hubbub, !hubbub->ctx->dc->debug.disable_stutter); + + return wm_pending; } void hubbub21_wm_read_state(struct hubbub *hubbub, diff --git a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_hubbub.h b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_hubbub.h index c4840dfb1fa5..ef3ef28509ed 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_hubbub.h +++ b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_hubbub.h @@ -113,22 +113,22 @@ void dcn21_dchvm_init(struct hubbub *hubbub); int hubbub21_init_dchub(struct hubbub *hubbub, struct dcn_hubbub_phys_addr_config *pa_config); -void hubbub21_program_watermarks( +bool hubbub21_program_watermarks( struct hubbub *hubbub, struct dcn_watermark_set *watermarks, unsigned int refclk_mhz, bool safe_to_lower); -void hubbub21_program_urgent_watermarks( +bool hubbub21_program_urgent_watermarks( struct hubbub *hubbub, struct dcn_watermark_set *watermarks, unsigned int refclk_mhz, bool safe_to_lower); -void hubbub21_program_stutter_watermarks( +bool hubbub21_program_stutter_watermarks( struct hubbub *hubbub, struct dcn_watermark_set *watermarks, unsigned int refclk_mhz, bool safe_to_lower); -void hubbub21_program_pstate_watermarks( +bool hubbub21_program_pstate_watermarks( struct hubbub *hubbub, struct dcn_watermark_set *watermarks, unsigned int refclk_mhz, diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/dchubbub.h b/drivers/gpu/drm/amd/display/dc/inc/hw/dchubbub.h index c0dc1d0f5cae..f5dd0cc73c63 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/dchubbub.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/dchubbub.h @@ -134,7 +134,7 @@ struct hubbub_funcs { unsigned int dccg_ref_freq_inKhz, unsigned int *dchub_ref_freq_inKhz); - void (*program_watermarks)( + bool (*program_watermarks)( struct hubbub *hubbub, struct dcn_watermark_set *watermarks, unsigned int refclk_mhz, -- cgit From 4a680b455f050f129ac845e52d19cb7c7299ae32 Mon Sep 17 00:00:00 2001 From: Sung Lee Date: Tue, 18 Feb 2020 15:53:28 -0500 Subject: drm/amd/display: Make clock table struct more accessible [WHY] Currently clock table struct is very far down in the bounding box struct making it hard to find while debugging, especially when using the dal3dbgext. [HOW] Move it up so it is the first struct defined, and therefore much easier to find and access. Signed-off-by: Sung Lee Reviewed-by: Eric Yang Acked-by: Rodrigo Siqueira Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dml/display_mode_structs.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu/drm/amd/display') diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_mode_structs.h b/drivers/gpu/drm/amd/display/dc/dml/display_mode_structs.h index 114f861f7f3e..a56b611db15e 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/display_mode_structs.h +++ b/drivers/gpu/drm/amd/display/dc/dml/display_mode_structs.h @@ -68,6 +68,7 @@ struct _vcs_dpi_voltage_scaling_st { }; struct _vcs_dpi_soc_bounding_box_st { + struct _vcs_dpi_voltage_scaling_st clock_limits[MAX_CLOCK_LIMIT_STATES]; double sr_exit_time_us; double sr_enter_plus_exit_time_us; double urgent_latency_us; @@ -111,7 +112,6 @@ struct _vcs_dpi_soc_bounding_box_st { double xfc_xbuf_latency_tolerance_us; int use_urgent_burst_bw; unsigned int num_states; - struct _vcs_dpi_voltage_scaling_st clock_limits[MAX_CLOCK_LIMIT_STATES]; double min_dcfclk; bool do_urgent_latency_adjustment; double urgent_latency_adjustment_fabric_clock_component_us; -- cgit From d9758768a672e9e665cba4171c022e5069b71aff Mon Sep 17 00:00:00 2001 From: George Shen Date: Thu, 30 Jan 2020 15:57:36 -0500 Subject: drm/amd/display: Temporarily disable stutter on MPO transition [Why] Underflow sometimes occurs during transition into MPO with stutter enabled. [How] When transitioning into MPO, disable stutter. Re-enable stutter within one frame. Signed-off-by: George Shen Signed-off-by: Tony Cheng Reviewed-by: Eric Yang Acked-by: Rodrigo Siqueira Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 14 ++++++++++++++ drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c | 19 ++++++++++++++++++- drivers/gpu/drm/amd/display/dc/dcn21/dcn21_hubbub.c | 1 + drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c | 1 + .../gpu/drm/amd/display/dc/inc/hw_sequencer_private.h | 3 +++ 5 files changed, 37 insertions(+), 1 deletion(-) (limited to 'drivers/gpu/drm/amd/display') diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 8e29403f963a..385250e1e3fd 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -2932,6 +2932,7 @@ void dcn10_update_pending_status(struct pipe_ctx *pipe_ctx) struct dc_plane_state *plane_state = pipe_ctx->plane_state; struct timing_generator *tg = pipe_ctx->stream_res.tg; bool flip_pending; + struct dc *dc = plane_state->ctx->dc; if (plane_state == NULL) return; @@ -2949,6 +2950,19 @@ void dcn10_update_pending_status(struct pipe_ctx *pipe_ctx) plane_state->status.is_right_eye = !tg->funcs->is_stereo_left_eye(pipe_ctx->stream_res.tg); } + + if (dc->hwseq->wa_state.disallow_self_refresh_during_multi_plane_transition_applied) { + struct dce_hwseq *hwseq = dc->hwseq; + struct timing_generator *tg = dc->res_pool->timing_generators[0]; + unsigned int cur_frame = tg->funcs->get_frame_count(tg); + + if (cur_frame != hwseq->wa_state.disallow_self_refresh_during_multi_plane_transition_applied_on_frame) { + struct hubbub *hubbub = dc->res_pool->hubbub; + + hubbub->funcs->allow_self_refresh_control(hubbub, !dc->debug.disable_stutter); + hwseq->wa_state.disallow_self_refresh_during_multi_plane_transition_applied = false; + } + } } void dcn10_update_dchub(struct dce_hwseq *hws, struct dchub_init_data *dh_data) diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c index cf13b1db1025..97c0c8ced8e5 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c @@ -1584,6 +1584,7 @@ void dcn20_post_unlock_program_front_end( { int i; const unsigned int TIMEOUT_FOR_PIPE_ENABLE_MS = 100; + struct dce_hwseq *hwseq = dc->hwseq; DC_LOGGER_INIT(dc->ctx->logger); @@ -1611,8 +1612,24 @@ void dcn20_post_unlock_program_front_end( } /* WA to apply WM setting*/ - if (dc->hwseq->wa.DEGVIDCN21) + if (hwseq->wa.DEGVIDCN21) dc->res_pool->hubbub->funcs->apply_DEDCN21_147_wa(dc->res_pool->hubbub); + + + /* WA for stutter underflow during MPO transitions when adding 2nd plane */ + if (hwseq->wa.disallow_self_refresh_during_multi_plane_transition) { + + if (dc->current_state->stream_status[0].plane_count == 1 && + context->stream_status[0].plane_count > 1) { + + struct timing_generator *tg = dc->res_pool->timing_generators[0]; + + dc->res_pool->hubbub->funcs->allow_self_refresh_control(dc->res_pool->hubbub, false); + + hwseq->wa_state.disallow_self_refresh_during_multi_plane_transition_applied = true; + hwseq->wa_state.disallow_self_refresh_during_multi_plane_transition_applied_on_frame = tg->funcs->get_frame_count(tg); + } + } } void dcn20_prepare_bandwidth( diff --git a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_hubbub.c b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_hubbub.c index 8440975206e0..5e2d14b897af 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_hubbub.c +++ b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_hubbub.c @@ -702,6 +702,7 @@ static const struct hubbub_funcs hubbub21_funcs = { .wm_read_state = hubbub21_wm_read_state, .get_dchub_ref_freq = hubbub2_get_dchub_ref_freq, .program_watermarks = hubbub21_program_watermarks, + .allow_self_refresh_control = hubbub1_allow_self_refresh_control, .apply_DEDCN21_147_wa = hubbub21_apply_DEDCN21_147_wa, }; diff --git a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c index f453de10aa2d..aa73025c1747 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c @@ -1564,6 +1564,7 @@ static struct dce_hwseq *dcn21_hwseq_create( hws->shifts = &hwseq_shift; hws->masks = &hwseq_mask; hws->wa.DEGVIDCN21 = true; + hws->wa.disallow_self_refresh_during_multi_plane_transition = true; } return hws; } diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer_private.h b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer_private.h index c5511e6157af..b1d736cbcd5a 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer_private.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer_private.h @@ -40,10 +40,13 @@ struct dce_hwseq_wa { bool false_optc_underflow; bool DEGVIDCN10_254; bool DEGVIDCN21; + bool disallow_self_refresh_during_multi_plane_transition; }; struct hwseq_wa_state { bool DEGVIDCN10_253_applied; + bool disallow_self_refresh_during_multi_plane_transition_applied; + unsigned int disallow_self_refresh_during_multi_plane_transition_applied_on_frame; }; struct pipe_ctx; -- cgit From e2c9529f00419dd4d4c8b62defeb3300eee683f2 Mon Sep 17 00:00:00 2001 From: Jaehyun Chung Date: Tue, 18 Feb 2020 18:01:19 -0500 Subject: drm/amd/display: Access patches from stream for ignore MSA monitor patch [Why] System will crash when trying to access local sink in core_link_enable_stream in MST case. [How] Access patches directly from stream. Signed-off-by: Jaehyun Chung Reviewed-by: Aric Cyr Reviewed-by: Ashley Thomas Acked-by: Rodrigo Siqueira Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/gpu/drm/amd/display') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index 2ccc2db93f5d..02e1ad318203 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -3095,8 +3095,8 @@ void core_link_enable_stream( dc->hwss.unblank_stream(pipe_ctx, &pipe_ctx->stream->link->cur_link_settings); - if (stream->link->local_sink->edid_caps.panel_patch.delay_ignore_msa > 0) - msleep(stream->link->local_sink->edid_caps.panel_patch.delay_ignore_msa); + if (stream->sink_patches.delay_ignore_msa > 0) + msleep(stream->sink_patches.delay_ignore_msa); if (dc_is_dp_signal(pipe_ctx->stream->signal)) enable_stream_features(pipe_ctx); -- cgit From cab5dec425f19f3d4eeca0d8e073578cbed66d8d Mon Sep 17 00:00:00 2001 From: Yu-ting Shen Date: Fri, 7 Feb 2020 15:19:31 +0800 Subject: drm/amd/display: limit display clock to 100MHz to avoid FIFO error [Why] when changing display clock, SMU need to use power up DFS and use DENTIST to ramp DFS DID to switch target frequency before switching back to bypass. [How] fixed the minimum display clock to 100MHz, it's W/A the same with PCO. Signed-off-by: Yu-ting Shen Reviewed-by: Tony Cheng Acked-by: Rodrigo Siqueira Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c | 3 +++ drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c | 1 + 2 files changed, 4 insertions(+) (limited to 'drivers/gpu/drm/amd/display') diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c index 883ecd2ed4c8..78971b6b195c 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c @@ -2786,6 +2786,9 @@ void dcn20_calculate_dlg_params( != dm_dram_clock_change_unsupported; context->bw_ctx.bw.dcn.clk.dppclk_khz = 0; + if (context->bw_ctx.bw.dcn.clk.dispclk_khz < dc->debug.min_disp_clk_khz) + context->bw_ctx.bw.dcn.clk.dispclk_khz = dc->debug.min_disp_clk_khz; + /* * An artifact of dml pipe split/odm is that pipes get merged back together for * calculation. Therefore we need to only extract for first pipe in ascending index order diff --git a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c index aa73025c1747..dce4966eca20 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c @@ -859,6 +859,7 @@ static const struct dc_debug_options debug_defaults_drv = { .timing_trace = false, .clock_trace = true, .disable_pplib_clock_request = true, + .min_disp_clk_khz = 100000, .pipe_split_policy = MPC_SPLIT_AVOID_MULT_DISP, .force_single_disp_pipe_split = false, .disable_dcc = DCC_ENABLE, -- cgit From 0943629ceb1321c3ea1a1b81725303b835cb1dbc Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Fri, 21 Feb 2020 21:24:33 +0800 Subject: drm/amd/display: remove set but not used variable 'mc_vm_apt_default' drivers/gpu/drm/amd/amdgpu/../display/dc/dcn21/dcn21_hubp.c: In function hubp21_set_vm_system_aperture_settings: drivers/gpu/drm/amd/amdgpu/../display/dc/dcn21/dcn21_hubp.c:343:23: warning: variable mc_vm_apt_default set but not used [-Wunused-but-set-variable] It is never used, so remove it. Reported-by: Hulk Robot Signed-off-by: YueHaibing Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn21/dcn21_hubp.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'drivers/gpu/drm/amd/display') diff --git a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_hubp.c b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_hubp.c index aa7b0e7eb945..d285ba622d61 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_hubp.c +++ b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_hubp.c @@ -340,13 +340,9 @@ void hubp21_set_vm_system_aperture_settings(struct hubp *hubp, { struct dcn21_hubp *hubp21 = TO_DCN21_HUBP(hubp); - PHYSICAL_ADDRESS_LOC mc_vm_apt_default; PHYSICAL_ADDRESS_LOC mc_vm_apt_low; PHYSICAL_ADDRESS_LOC mc_vm_apt_high; - // The format of default addr is 48:12 of the 48 bit addr - mc_vm_apt_default.quad_part = apt->sys_default.quad_part >> 12; - // The format of high/low are 48:18 of the 48 bit addr mc_vm_apt_low.quad_part = apt->sys_low.quad_part >> 18; mc_vm_apt_high.quad_part = apt->sys_high.quad_part >> 18; -- cgit From e22bb5626cd6cd7c39cc2563ddb4b5d7d44dc91c Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 18 Feb 2020 13:20:30 -0500 Subject: drm/amdgpu/display: clean up hdcp workqueue handling Use the existence of the workqueue itself to determine when to enable HDCP features rather than sprinkling asic checks all over the code. Also add a check for the existence of the hdcp workqueue in the irq handling on the off chance we get and HPD RX interrupt with the CP bit set. This avoids a crash if the driver doesn't support HDCP for a particular asic. Fixes: 96a3b32e67236f ("drm/amd/display: only enable HDCP for DCN+") Bug: https://bugzilla.kernel.org/show_bug.cgi?id=206519 Reviewed-by: Bhawanpreet Lakha Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'drivers/gpu/drm/amd/display') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index e768a31441cc..58fc678b7902 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -1984,7 +1984,7 @@ static void handle_hpd_irq(void *param) mutex_lock(&aconnector->hpd_lock); #ifdef CONFIG_DRM_AMD_DC_HDCP - if (adev->asic_type >= CHIP_RAVEN) + if (adev->dm.hdcp_workqueue) hdcp_reset_display(adev->dm.hdcp_workqueue, aconnector->dc_link->link_index); #endif if (aconnector->fake_enable) @@ -2161,8 +2161,10 @@ static void handle_hpd_rx_irq(void *param) } } #ifdef CONFIG_DRM_AMD_DC_HDCP - if (hpd_irq_data.bytes.device_service_irq.bits.CP_IRQ) - hdcp_handle_cpirq(adev->dm.hdcp_workqueue, aconnector->base.index); + if (hpd_irq_data.bytes.device_service_irq.bits.CP_IRQ) { + if (adev->dm.hdcp_workqueue) + hdcp_handle_cpirq(adev->dm.hdcp_workqueue, aconnector->base.index); + } #endif if ((dc_link->cur_link_settings.lane_count != LANE_COUNT_UNKNOWN) || (dc_link->type == dc_connection_mst_branch)) @@ -5833,7 +5835,7 @@ void amdgpu_dm_connector_init_helper(struct amdgpu_display_manager *dm, drm_connector_attach_vrr_capable_property( &aconnector->base); #ifdef CONFIG_DRM_AMD_DC_HDCP - if (adev->asic_type >= CHIP_RAVEN) + if (adev->dm.hdcp_workqueue) drm_connector_attach_content_protection_property(&aconnector->base, true); #endif } -- cgit From 4074892967aeb4315a7700888f23d9e740fdb2f2 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 4 Feb 2020 17:02:34 -0500 Subject: drm/amdgpu: don't call drm_connector_register for non-MST ports MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The core does this for us now. Tested-by: Thomas Zimmermann Acked-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/gpu/drm/amd/display') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 58fc678b7902..73bb36c63ea8 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -5972,7 +5972,6 @@ static int amdgpu_dm_connector_init(struct amdgpu_display_manager *dm, drm_connector_attach_encoder( &aconnector->base, &aencoder->base); - drm_connector_register(&aconnector->base); #if defined(CONFIG_DEBUG_FS) connector_debugfs_init(aconnector); aconnector->debugfs_dpcd_address = 0; -- cgit From d090e7db5a2f19df1fe1bff251b872483e50b79b Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 25 Feb 2020 11:21:30 -0500 Subject: drm/amdgpu/display: move debugfs init into core amdgpu debugfs (v2) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In order to remove the load and unload drm callbacks, we need to reorder the init sequence to move all the drm debugfs file handling. Do this for display. v2: add config guard for DC Tested-by: Thomas Zimmermann Reviewed-by: Harry Wentland (v1) Acked-by: Christian König (v1) Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 5 ----- 1 file changed, 5 deletions(-) (limited to 'drivers/gpu/drm/amd/display') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 73bb36c63ea8..200733d503ad 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -1008,11 +1008,6 @@ static int amdgpu_dm_init(struct amdgpu_device *adev) goto error; } -#if defined(CONFIG_DEBUG_FS) - if (dtn_debugfs_init(adev)) - DRM_ERROR("amdgpu: failed initialize dtn debugfs support.\n"); -#endif - DRM_DEBUG_DRIVER("KMS initialized.\n"); return 0; -- cgit From 7b99330c8f084abf4957a7abb7b2061be035b2a2 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 4 Feb 2020 17:07:39 -0500 Subject: drm/amd/display: move dpcd debugfs members setup MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Into the function that creates the debugfs files rather than setting them explicitly in the callers. Tested-by: Thomas Zimmermann Reviewed-by: Harry Wentland Acked-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 2 -- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c | 3 +++ drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c | 2 -- 3 files changed, 3 insertions(+), 4 deletions(-) (limited to 'drivers/gpu/drm/amd/display') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 200733d503ad..ecbf3810dc44 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -5969,8 +5969,6 @@ static int amdgpu_dm_connector_init(struct amdgpu_display_manager *dm, #if defined(CONFIG_DEBUG_FS) connector_debugfs_init(aconnector); - aconnector->debugfs_dpcd_address = 0; - aconnector->debugfs_dpcd_size = 0; #endif if (connector_type == DRM_MODE_CONNECTOR_DisplayPort diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c index 8ec3b4335c69..0461fecd68db 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c @@ -1090,6 +1090,9 @@ void connector_debugfs_init(struct amdgpu_dm_connector *connector) debugfs_create_file_unsafe("force_yuv420_output", 0644, dir, connector, &force_yuv420_output_fops); + connector->debugfs_dpcd_address = 0; + connector->debugfs_dpcd_size = 0; + } /* diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c index 5672f7765919..3959c942c88b 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c @@ -158,8 +158,6 @@ amdgpu_dm_mst_connector_late_register(struct drm_connector *connector) #if defined(CONFIG_DEBUG_FS) connector_debugfs_init(amdgpu_dm_connector); - amdgpu_dm_connector->debugfs_dpcd_address = 0; - amdgpu_dm_connector->debugfs_dpcd_size = 0; #endif return drm_dp_mst_connector_late_register(connector, port); -- cgit From 14f04fa4834a515146115bca755c76bc9b73aa8c Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 4 Feb 2020 17:11:18 -0500 Subject: drm/amdgpu/display: add a late register connector callback MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit To handle debugfs setup on non DP MST connectors. Tested-by: Thomas Zimmermann Reviewed-by: Harry Wentland Acked-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) (limited to 'drivers/gpu/drm/amd/display') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index ecbf3810dc44..dd35ac0276a2 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -4619,6 +4619,19 @@ amdgpu_dm_connector_atomic_duplicate_state(struct drm_connector *connector) return &new_state->base; } +static int +amdgpu_dm_connector_late_register(struct drm_connector *connector) +{ + struct amdgpu_dm_connector *amdgpu_dm_connector = + to_amdgpu_dm_connector(connector); + +#if defined(CONFIG_DEBUG_FS) + connector_debugfs_init(amdgpu_dm_connector); +#endif + + return 0; +} + static const struct drm_connector_funcs amdgpu_dm_connector_funcs = { .reset = amdgpu_dm_connector_funcs_reset, .detect = amdgpu_dm_connector_detect, @@ -4628,6 +4641,7 @@ static const struct drm_connector_funcs amdgpu_dm_connector_funcs = { .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, .atomic_set_property = amdgpu_dm_connector_atomic_set_property, .atomic_get_property = amdgpu_dm_connector_atomic_get_property, + .late_register = amdgpu_dm_connector_late_register, .early_unregister = amdgpu_dm_connector_unregister }; @@ -5967,10 +5981,6 @@ static int amdgpu_dm_connector_init(struct amdgpu_display_manager *dm, drm_connector_attach_encoder( &aconnector->base, &aencoder->base); -#if defined(CONFIG_DEBUG_FS) - connector_debugfs_init(aconnector); -#endif - if (connector_type == DRM_MODE_CONNECTOR_DisplayPort || connector_type == DRM_MODE_CONNECTOR_eDP) amdgpu_dm_initialize_dp_connector(dm, aconnector); -- cgit From 405a1f9090d1acec75aeb86569da60beca9fe68f Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Wed, 5 Feb 2020 10:18:04 -0500 Subject: drm/amdgpu/display: split dp connector registration (v4) Split into init and register functions to avoid a segfault in some configs when the load/unload callbacks are removed. v2: - add back accidently dropped has_aux setting - set dev in late_register v3: - fix dp cec ordering v4: - squash in kdev reference fix Reviewed-by: Daniel Vetter Tested-by: Thomas Zimmermann Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'drivers/gpu/drm/amd/display') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c index 3959c942c88b..d7a7dc0c256e 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c @@ -155,6 +155,12 @@ amdgpu_dm_mst_connector_late_register(struct drm_connector *connector) struct amdgpu_dm_connector *amdgpu_dm_connector = to_amdgpu_dm_connector(connector); struct drm_dp_mst_port *port = amdgpu_dm_connector->port; + int r; + + amdgpu_dm_connector->dm_dp_aux.aux.dev = connector->kdev; + r = drm_dp_aux_register(&amdgpu_dm_connector->dm_dp_aux.aux); + if (r) + return r; #if defined(CONFIG_DEBUG_FS) connector_debugfs_init(amdgpu_dm_connector); @@ -480,11 +486,10 @@ void amdgpu_dm_initialize_dp_connector(struct amdgpu_display_manager *dm, struct amdgpu_dm_connector *aconnector) { aconnector->dm_dp_aux.aux.name = "dmdc"; - aconnector->dm_dp_aux.aux.dev = aconnector->base.kdev; aconnector->dm_dp_aux.aux.transfer = dm_dp_aux_transfer; aconnector->dm_dp_aux.ddc_service = aconnector->dc_link->ddc; - drm_dp_aux_register(&aconnector->dm_dp_aux.aux); + drm_dp_aux_init(&aconnector->dm_dp_aux.aux); drm_dp_cec_register_connector(&aconnector->dm_dp_aux.aux, &aconnector->base); -- cgit From d95665c70844dd97aa3e900fd110cd1db68ede1a Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 25 Feb 2020 13:39:44 -0500 Subject: drm/amdgpu/display: don't call drm_dp_mst_connector_late_register (v2) Nothing else calls it. Not sure it's necessary. v2: remove unused port variable. Reviewed-by: Jerry (Fangzhi) Zuo Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/gpu/drm/amd/display') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c index d7a7dc0c256e..0ef0eeb16778 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c @@ -154,7 +154,6 @@ amdgpu_dm_mst_connector_late_register(struct drm_connector *connector) { struct amdgpu_dm_connector *amdgpu_dm_connector = to_amdgpu_dm_connector(connector); - struct drm_dp_mst_port *port = amdgpu_dm_connector->port; int r; amdgpu_dm_connector->dm_dp_aux.aux.dev = connector->kdev; @@ -166,7 +165,7 @@ amdgpu_dm_mst_connector_late_register(struct drm_connector *connector) connector_debugfs_init(amdgpu_dm_connector); #endif - return drm_dp_mst_connector_late_register(connector, port); + return r; } static void -- cgit