diff options
| -rw-r--r-- | drivers/gpu/drm/radeon/rs600.c | 130 |
1 files changed, 130 insertions, 0 deletions
diff --git a/drivers/gpu/drm/radeon/rs600.c b/drivers/gpu/drm/radeon/rs600.c index 84b26376027d..6364ba1d4153 100644 --- a/drivers/gpu/drm/radeon/rs600.c +++ b/drivers/gpu/drm/radeon/rs600.c | |||
| @@ -60,6 +60,107 @@ int rs600_mc_init(struct radeon_device *rdev) | |||
| 60 | return r; | 60 | return r; |
| 61 | return 0; | 61 | return 0; |
| 62 | } | 62 | } |
| 63 | |||
| 64 | /* hpd for digital panel detect/disconnect */ | ||
| 65 | bool rs600_hpd_sense(struct radeon_device *rdev, enum radeon_hpd_id hpd) | ||
| 66 | { | ||
| 67 | u32 tmp; | ||
| 68 | bool connected = false; | ||
| 69 | |||
| 70 | switch (hpd) { | ||
| 71 | case RADEON_HPD_1: | ||
| 72 | tmp = RREG32(R_007D04_DC_HOT_PLUG_DETECT1_INT_STATUS); | ||
| 73 | if (G_007D04_DC_HOT_PLUG_DETECT1_SENSE(tmp)) | ||
| 74 | connected = true; | ||
| 75 | break; | ||
| 76 | case RADEON_HPD_2: | ||
| 77 | tmp = RREG32(R_007D14_DC_HOT_PLUG_DETECT2_INT_STATUS); | ||
| 78 | if (G_007D14_DC_HOT_PLUG_DETECT2_SENSE(tmp)) | ||
| 79 | connected = true; | ||
| 80 | break; | ||
| 81 | default: | ||
| 82 | break; | ||
| 83 | } | ||
| 84 | return connected; | ||
| 85 | } | ||
| 86 | |||
| 87 | void rs600_hpd_set_polarity(struct radeon_device *rdev, | ||
| 88 | enum radeon_hpd_id hpd) | ||
| 89 | { | ||
| 90 | u32 tmp; | ||
| 91 | bool connected = rs600_hpd_sense(rdev, hpd); | ||
| 92 | |||
| 93 | switch (hpd) { | ||
| 94 | case RADEON_HPD_1: | ||
| 95 | tmp = RREG32(R_007D08_DC_HOT_PLUG_DETECT1_INT_CONTROL); | ||
| 96 | if (connected) | ||
| 97 | tmp &= ~S_007D08_DC_HOT_PLUG_DETECT1_INT_POLARITY(1); | ||
| 98 | else | ||
| 99 | tmp |= S_007D08_DC_HOT_PLUG_DETECT1_INT_POLARITY(1); | ||
| 100 | WREG32(R_007D08_DC_HOT_PLUG_DETECT1_INT_CONTROL, tmp); | ||
| 101 | break; | ||
| 102 | case RADEON_HPD_2: | ||
| 103 | tmp = RREG32(R_007D18_DC_HOT_PLUG_DETECT2_INT_CONTROL); | ||
| 104 | if (connected) | ||
| 105 | tmp &= ~S_007D18_DC_HOT_PLUG_DETECT2_INT_POLARITY(1); | ||
| 106 | else | ||
| 107 | tmp |= S_007D18_DC_HOT_PLUG_DETECT2_INT_POLARITY(1); | ||
| 108 | WREG32(R_007D18_DC_HOT_PLUG_DETECT2_INT_CONTROL, tmp); | ||
| 109 | break; | ||
| 110 | default: | ||
| 111 | break; | ||
| 112 | } | ||
| 113 | } | ||
| 114 | |||
| 115 | void rs600_hpd_init(struct radeon_device *rdev) | ||
| 116 | { | ||
| 117 | struct drm_device *dev = rdev->ddev; | ||
| 118 | struct drm_connector *connector; | ||
| 119 | |||
| 120 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { | ||
| 121 | struct radeon_connector *radeon_connector = to_radeon_connector(connector); | ||
| 122 | switch (radeon_connector->hpd.hpd) { | ||
| 123 | case RADEON_HPD_1: | ||
| 124 | WREG32(R_007D00_DC_HOT_PLUG_DETECT1_CONTROL, | ||
| 125 | S_007D00_DC_HOT_PLUG_DETECT1_EN(1)); | ||
| 126 | rdev->irq.hpd[0] = true; | ||
| 127 | break; | ||
| 128 | case RADEON_HPD_2: | ||
| 129 | WREG32(R_007D10_DC_HOT_PLUG_DETECT2_CONTROL, | ||
| 130 | S_007D10_DC_HOT_PLUG_DETECT2_EN(1)); | ||
| 131 | rdev->irq.hpd[1] = true; | ||
| 132 | break; | ||
| 133 | default: | ||
| 134 | break; | ||
| 135 | } | ||
| 136 | } | ||
| 137 | rs600_irq_set(rdev); | ||
| 138 | } | ||
| 139 | |||
| 140 | void rs600_hpd_fini(struct radeon_device *rdev) | ||
| 141 | { | ||
| 142 | struct drm_device *dev = rdev->ddev; | ||
| 143 | struct drm_connector *connector; | ||
| 144 | |||
| 145 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { | ||
| 146 | struct radeon_connector *radeon_connector = to_radeon_connector(connector); | ||
| 147 | switch (radeon_connector->hpd.hpd) { | ||
| 148 | case RADEON_HPD_1: | ||
| 149 | WREG32(R_007D00_DC_HOT_PLUG_DETECT1_CONTROL, | ||
| 150 | S_007D00_DC_HOT_PLUG_DETECT1_EN(0)); | ||
| 151 | rdev->irq.hpd[0] = false; | ||
| 152 | break; | ||
| 153 | case RADEON_HPD_2: | ||
| 154 | WREG32(R_007D10_DC_HOT_PLUG_DETECT2_CONTROL, | ||
| 155 | S_007D10_DC_HOT_PLUG_DETECT2_EN(0)); | ||
| 156 | rdev->irq.hpd[1] = false; | ||
| 157 | break; | ||
| 158 | default: | ||
| 159 | break; | ||
| 160 | } | ||
| 161 | } | ||
| 162 | } | ||
| 163 | |||
| 63 | /* | 164 | /* |
| 64 | * GART. | 165 | * GART. |
| 65 | */ | 166 | */ |
| @@ -209,6 +310,10 @@ int rs600_irq_set(struct radeon_device *rdev) | |||
| 209 | { | 310 | { |
| 210 | uint32_t tmp = 0; | 311 | uint32_t tmp = 0; |
| 211 | uint32_t mode_int = 0; | 312 | uint32_t mode_int = 0; |
| 313 | u32 hpd1 = RREG32(R_007D08_DC_HOT_PLUG_DETECT1_INT_CONTROL) & | ||
| 314 | ~S_007D08_DC_HOT_PLUG_DETECT1_INT_EN(1); | ||
| 315 | u32 hpd2 = RREG32(R_007D18_DC_HOT_PLUG_DETECT2_INT_CONTROL) & | ||
| 316 | ~S_007D18_DC_HOT_PLUG_DETECT2_INT_EN(1); | ||
| 212 | 317 | ||
| 213 | if (rdev->irq.sw_int) { | 318 | if (rdev->irq.sw_int) { |
| 214 | tmp |= S_000040_SW_INT_EN(1); | 319 | tmp |= S_000040_SW_INT_EN(1); |
| @@ -219,8 +324,16 @@ int rs600_irq_set(struct radeon_device *rdev) | |||
| 219 | if (rdev->irq.crtc_vblank_int[1]) { | 324 | if (rdev->irq.crtc_vblank_int[1]) { |
| 220 | mode_int |= S_006540_D2MODE_VBLANK_INT_MASK(1); | 325 | mode_int |= S_006540_D2MODE_VBLANK_INT_MASK(1); |
| 221 | } | 326 | } |
| 327 | if (rdev->irq.hpd[0]) { | ||
| 328 | hpd1 |= S_007D08_DC_HOT_PLUG_DETECT1_INT_EN(1); | ||
| 329 | } | ||
| 330 | if (rdev->irq.hpd[1]) { | ||
| 331 | hpd2 |= S_007D18_DC_HOT_PLUG_DETECT2_INT_EN(1); | ||
| 332 | } | ||
| 222 | WREG32(R_000040_GEN_INT_CNTL, tmp); | 333 | WREG32(R_000040_GEN_INT_CNTL, tmp); |
| 223 | WREG32(R_006540_DxMODE_INT_MASK, mode_int); | 334 | WREG32(R_006540_DxMODE_INT_MASK, mode_int); |
| 335 | WREG32(R_007D08_DC_HOT_PLUG_DETECT1_INT_CONTROL, hpd1); | ||
| 336 | WREG32(R_007D18_DC_HOT_PLUG_DETECT2_INT_CONTROL, hpd2); | ||
| 224 | return 0; | 337 | return 0; |
| 225 | } | 338 | } |
| 226 | 339 | ||
| @@ -228,6 +341,7 @@ static inline uint32_t rs600_irq_ack(struct radeon_device *rdev, u32 *r500_disp_ | |||
| 228 | { | 341 | { |
| 229 | uint32_t irqs = RREG32(R_000044_GEN_INT_STATUS); | 342 | uint32_t irqs = RREG32(R_000044_GEN_INT_STATUS); |
| 230 | uint32_t irq_mask = ~C_000044_SW_INT; | 343 | uint32_t irq_mask = ~C_000044_SW_INT; |
| 344 | u32 tmp; | ||
| 231 | 345 | ||
| 232 | if (G_000044_DISPLAY_INT_STAT(irqs)) { | 346 | if (G_000044_DISPLAY_INT_STAT(irqs)) { |
| 233 | *r500_disp_int = RREG32(R_007EDC_DISP_INTERRUPT_STATUS); | 347 | *r500_disp_int = RREG32(R_007EDC_DISP_INTERRUPT_STATUS); |
| @@ -239,6 +353,16 @@ static inline uint32_t rs600_irq_ack(struct radeon_device *rdev, u32 *r500_disp_ | |||
| 239 | WREG32(R_006D34_D2MODE_VBLANK_STATUS, | 353 | WREG32(R_006D34_D2MODE_VBLANK_STATUS, |
| 240 | S_006D34_D2MODE_VBLANK_ACK(1)); | 354 | S_006D34_D2MODE_VBLANK_ACK(1)); |
| 241 | } | 355 | } |
| 356 | if (G_007EDC_DC_HOT_PLUG_DETECT1_INTERRUPT(*r500_disp_int)) { | ||
| 357 | tmp = RREG32(R_007D08_DC_HOT_PLUG_DETECT1_INT_CONTROL); | ||
| 358 | tmp |= S_007D08_DC_HOT_PLUG_DETECT1_INT_ACK(1); | ||
| 359 | WREG32(R_007D08_DC_HOT_PLUG_DETECT1_INT_CONTROL, tmp); | ||
| 360 | } | ||
| 361 | if (G_007EDC_DC_HOT_PLUG_DETECT2_INTERRUPT(*r500_disp_int)) { | ||
| 362 | tmp = RREG32(R_007D18_DC_HOT_PLUG_DETECT2_INT_CONTROL); | ||
| 363 | tmp |= S_007D18_DC_HOT_PLUG_DETECT2_INT_ACK(1); | ||
| 364 | WREG32(R_007D18_DC_HOT_PLUG_DETECT2_INT_CONTROL, tmp); | ||
| 365 | } | ||
| 242 | } else { | 366 | } else { |
| 243 | *r500_disp_int = 0; | 367 | *r500_disp_int = 0; |
| 244 | } | 368 | } |
| @@ -278,6 +402,12 @@ int rs600_irq_process(struct radeon_device *rdev) | |||
| 278 | drm_handle_vblank(rdev->ddev, 0); | 402 | drm_handle_vblank(rdev->ddev, 0); |
| 279 | if (G_007EDC_LB_D2_VBLANK_INTERRUPT(r500_disp_int)) | 403 | if (G_007EDC_LB_D2_VBLANK_INTERRUPT(r500_disp_int)) |
| 280 | drm_handle_vblank(rdev->ddev, 1); | 404 | drm_handle_vblank(rdev->ddev, 1); |
| 405 | if (G_007EDC_DC_HOT_PLUG_DETECT1_INTERRUPT(r500_disp_int)) { | ||
| 406 | DRM_INFO("HPD1\n"); | ||
| 407 | } | ||
| 408 | if (G_007EDC_DC_HOT_PLUG_DETECT2_INTERRUPT(r500_disp_int)) { | ||
| 409 | DRM_INFO("HPD2\n"); | ||
| 410 | } | ||
| 281 | status = rs600_irq_ack(rdev, &r500_disp_int); | 411 | status = rs600_irq_ack(rdev, &r500_disp_int); |
| 282 | } | 412 | } |
| 283 | if (rdev->msi_enabled) { | 413 | if (rdev->msi_enabled) { |
