drm/amdgpu: Clear the hotplug interrupt ack bit before hpd initialization
authorQiang Ma <maqianga@uniontech.com>
Wed, 31 Jan 2024 07:57:03 +0000 (15:57 +0800)
committerAlex Deucher <alexander.deucher@amd.com>
Wed, 7 Feb 2024 15:01:10 +0000 (10:01 -0500)
Problem:
The computer in the bios initialization process, unplug the HDMI display,
wait until the system up, plug in the HDMI display, did not enter the
hotplug interrupt function, the display is not bright.

Fix:
After the above problem occurs, and the hpd ack interrupt bit is 1,
the interrupt should be cleared during hpd_init initialization so that
when the driver is ready, it can respond to the hpd interrupt normally.

Signed-off-by: Qiang Ma <maqianga@uniontech.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/amd/amdgpu/dce_v10_0.c
drivers/gpu/drm/amd/amdgpu/dce_v11_0.c
drivers/gpu/drm/amd/amdgpu/dce_v6_0.c
drivers/gpu/drm/amd/amdgpu/dce_v8_0.c

index 587ee632a3b8fddb2a99cb54d0f246f0e1b1ffd0..221af054d8746994fc823ff2547255133c7d092e 100644 (file)
@@ -52,6 +52,7 @@
 
 static void dce_v10_0_set_display_funcs(struct amdgpu_device *adev);
 static void dce_v10_0_set_irq_funcs(struct amdgpu_device *adev);
+static void dce_v10_0_hpd_int_ack(struct amdgpu_device *adev, int hpd);
 
 static const u32 crtc_offsets[] = {
        CRTC0_REGISTER_OFFSET,
@@ -364,6 +365,7 @@ static void dce_v10_0_hpd_init(struct amdgpu_device *adev)
                                    AMDGPU_HPD_DISCONNECT_INT_DELAY_IN_MS);
                WREG32(mmDC_HPD_TOGGLE_FILT_CNTL + hpd_offsets[amdgpu_connector->hpd.hpd], tmp);
 
+               dce_v10_0_hpd_int_ack(adev, amdgpu_connector->hpd.hpd);
                dce_v10_0_hpd_set_polarity(adev, amdgpu_connector->hpd.hpd);
                amdgpu_irq_get(adev, &adev->hpd_irq,
                               amdgpu_connector->hpd.hpd);
index f22ec27365bd251aa448d6b36b199becbe29598f..69e8b0db6cf7023d8ee3a763eda90be938c73ec5 100644 (file)
@@ -52,6 +52,7 @@
 
 static void dce_v11_0_set_display_funcs(struct amdgpu_device *adev);
 static void dce_v11_0_set_irq_funcs(struct amdgpu_device *adev);
+static void dce_v11_0_hpd_int_ack(struct amdgpu_device *adev, int hpd);
 
 static const u32 crtc_offsets[] =
 {
@@ -388,6 +389,7 @@ static void dce_v11_0_hpd_init(struct amdgpu_device *adev)
                                    AMDGPU_HPD_DISCONNECT_INT_DELAY_IN_MS);
                WREG32(mmDC_HPD_TOGGLE_FILT_CNTL + hpd_offsets[amdgpu_connector->hpd.hpd], tmp);
 
+               dce_v11_0_hpd_int_ack(adev, amdgpu_connector->hpd.hpd);
                dce_v11_0_hpd_set_polarity(adev, amdgpu_connector->hpd.hpd);
                amdgpu_irq_get(adev, &adev->hpd_irq, amdgpu_connector->hpd.hpd);
        }
index 4dbe9b3259b50dc62bb131442010f235e587759e..60d40201fdd17730f43ce9fe3394958c5a8cac64 100644 (file)
@@ -273,6 +273,21 @@ static void dce_v6_0_hpd_set_polarity(struct amdgpu_device *adev,
        WREG32(mmDC_HPD1_INT_CONTROL + hpd_offsets[hpd], tmp);
 }
 
+static void dce_v6_0_hpd_int_ack(struct amdgpu_device *adev,
+                                int hpd)
+{
+       u32 tmp;
+
+       if (hpd >= adev->mode_info.num_hpd) {
+               DRM_DEBUG("invalid hdp %d\n", hpd);
+               return;
+       }
+
+       tmp = RREG32(mmDC_HPD1_INT_CONTROL + hpd_offsets[hpd]);
+       tmp |= DC_HPD1_INT_CONTROL__DC_HPD1_INT_ACK_MASK;
+       WREG32(mmDC_HPD1_INT_CONTROL + hpd_offsets[hpd], tmp);
+}
+
 /**
  * dce_v6_0_hpd_init - hpd setup callback.
  *
@@ -312,6 +327,7 @@ static void dce_v6_0_hpd_init(struct amdgpu_device *adev)
                        continue;
                }
 
+               dce_v6_0_hpd_int_ack(adev, amdgpu_connector->hpd.hpd);
                dce_v6_0_hpd_set_polarity(adev, amdgpu_connector->hpd.hpd);
                amdgpu_irq_get(adev, &adev->hpd_irq, amdgpu_connector->hpd.hpd);
        }
@@ -3089,7 +3105,7 @@ static int dce_v6_0_hpd_irq(struct amdgpu_device *adev,
                            struct amdgpu_irq_src *source,
                            struct amdgpu_iv_entry *entry)
 {
-       uint32_t disp_int, mask, tmp;
+       uint32_t disp_int, mask;
        unsigned hpd;
 
        if (entry->src_data[0] >= adev->mode_info.num_hpd) {
@@ -3102,9 +3118,7 @@ static int dce_v6_0_hpd_irq(struct amdgpu_device *adev,
        mask = interrupt_status_offsets[hpd].hpd;
 
        if (disp_int & mask) {
-               tmp = RREG32(mmDC_HPD1_INT_CONTROL + hpd_offsets[hpd]);
-               tmp |= DC_HPD1_INT_CONTROL__DC_HPD1_INT_ACK_MASK;
-               WREG32(mmDC_HPD1_INT_CONTROL + hpd_offsets[hpd], tmp);
+               dce_v6_0_hpd_int_ack(adev, hpd);
                schedule_delayed_work(&adev->hotplug_work, 0);
                DRM_DEBUG("IH: HPD%d\n", hpd + 1);
        }
index 05bcce23385ec08e2ec8e424e865382794de405b..5a5fcc45e452102bcfa83772b4ab3d85337b5e36 100644 (file)
@@ -265,6 +265,21 @@ static void dce_v8_0_hpd_set_polarity(struct amdgpu_device *adev,
        WREG32(mmDC_HPD1_INT_CONTROL + hpd_offsets[hpd], tmp);
 }
 
+static void dce_v8_0_hpd_int_ack(struct amdgpu_device *adev,
+                                int hpd)
+{
+       u32 tmp;
+
+       if (hpd >= adev->mode_info.num_hpd) {
+               DRM_DEBUG("invalid hdp %d\n", hpd);
+               return;
+       }
+
+       tmp = RREG32(mmDC_HPD1_INT_CONTROL + hpd_offsets[hpd]);
+       tmp |= DC_HPD1_INT_CONTROL__DC_HPD1_INT_ACK_MASK;
+       WREG32(mmDC_HPD1_INT_CONTROL + hpd_offsets[hpd], tmp);
+}
+
 /**
  * dce_v8_0_hpd_init - hpd setup callback.
  *
@@ -304,6 +319,7 @@ static void dce_v8_0_hpd_init(struct amdgpu_device *adev)
                        continue;
                }
 
+               dce_v8_0_hpd_int_ack(adev, amdgpu_connector->hpd.hpd);
                dce_v8_0_hpd_set_polarity(adev, amdgpu_connector->hpd.hpd);
                amdgpu_irq_get(adev, &adev->hpd_irq, amdgpu_connector->hpd.hpd);
        }
@@ -3177,7 +3193,7 @@ static int dce_v8_0_hpd_irq(struct amdgpu_device *adev,
                            struct amdgpu_irq_src *source,
                            struct amdgpu_iv_entry *entry)
 {
-       uint32_t disp_int, mask, tmp;
+       uint32_t disp_int, mask;
        unsigned hpd;
 
        if (entry->src_data[0] >= adev->mode_info.num_hpd) {
@@ -3190,9 +3206,7 @@ static int dce_v8_0_hpd_irq(struct amdgpu_device *adev,
        mask = interrupt_status_offsets[hpd].hpd;
 
        if (disp_int & mask) {
-               tmp = RREG32(mmDC_HPD1_INT_CONTROL + hpd_offsets[hpd]);
-               tmp |= DC_HPD1_INT_CONTROL__DC_HPD1_INT_ACK_MASK;
-               WREG32(mmDC_HPD1_INT_CONTROL + hpd_offsets[hpd], tmp);
+               dce_v8_0_hpd_int_ack(adev, hpd);
                schedule_delayed_work(&adev->hotplug_work, 0);
                DRM_DEBUG("IH: HPD%d\n", hpd + 1);
        }