diff options
| -rw-r--r-- | drivers/gpu/drm/radeon/r100.c | 106 |
1 files changed, 104 insertions, 2 deletions
diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c index 109096802e66..2b534c528aaf 100644 --- a/drivers/gpu/drm/radeon/r100.c +++ b/drivers/gpu/drm/radeon/r100.c | |||
| @@ -65,6 +65,95 @@ MODULE_FIRMWARE(FIRMWARE_R520); | |||
| 65 | * r100,rv100,rs100,rv200,rs200,r200,rv250,rs300,rv280 | 65 | * r100,rv100,rs100,rv200,rs200,r200,rv250,rs300,rv280 |
| 66 | */ | 66 | */ |
| 67 | 67 | ||
| 68 | /* hpd for digital panel detect/disconnect */ | ||
| 69 | bool r100_hpd_sense(struct radeon_device *rdev, enum radeon_hpd_id hpd) | ||
| 70 | { | ||
| 71 | bool connected = false; | ||
| 72 | |||
| 73 | switch (hpd) { | ||
| 74 | case RADEON_HPD_1: | ||
| 75 | if (RREG32(RADEON_FP_GEN_CNTL) & RADEON_FP_DETECT_SENSE) | ||
| 76 | connected = true; | ||
| 77 | break; | ||
| 78 | case RADEON_HPD_2: | ||
| 79 | if (RREG32(RADEON_FP2_GEN_CNTL) & RADEON_FP2_DETECT_SENSE) | ||
| 80 | connected = true; | ||
| 81 | break; | ||
| 82 | default: | ||
| 83 | break; | ||
| 84 | } | ||
| 85 | return connected; | ||
| 86 | } | ||
| 87 | |||
| 88 | void r100_hpd_set_polarity(struct radeon_device *rdev, | ||
| 89 | enum radeon_hpd_id hpd) | ||
| 90 | { | ||
| 91 | u32 tmp; | ||
| 92 | bool connected = r100_hpd_sense(rdev, hpd); | ||
| 93 | |||
| 94 | switch (hpd) { | ||
| 95 | case RADEON_HPD_1: | ||
| 96 | tmp = RREG32(RADEON_FP_GEN_CNTL); | ||
| 97 | if (connected) | ||
| 98 | tmp &= ~RADEON_FP_DETECT_INT_POL; | ||
| 99 | else | ||
| 100 | tmp |= RADEON_FP_DETECT_INT_POL; | ||
| 101 | WREG32(RADEON_FP_GEN_CNTL, tmp); | ||
| 102 | break; | ||
| 103 | case RADEON_HPD_2: | ||
| 104 | tmp = RREG32(RADEON_FP2_GEN_CNTL); | ||
| 105 | if (connected) | ||
| 106 | tmp &= ~RADEON_FP2_DETECT_INT_POL; | ||
| 107 | else | ||
| 108 | tmp |= RADEON_FP2_DETECT_INT_POL; | ||
| 109 | WREG32(RADEON_FP2_GEN_CNTL, tmp); | ||
| 110 | break; | ||
| 111 | default: | ||
| 112 | break; | ||
| 113 | } | ||
| 114 | } | ||
| 115 | |||
| 116 | void r100_hpd_init(struct radeon_device *rdev) | ||
| 117 | { | ||
| 118 | struct drm_device *dev = rdev->ddev; | ||
| 119 | struct drm_connector *connector; | ||
| 120 | |||
| 121 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { | ||
| 122 | struct radeon_connector *radeon_connector = to_radeon_connector(connector); | ||
| 123 | switch (radeon_connector->hpd.hpd) { | ||
| 124 | case RADEON_HPD_1: | ||
| 125 | rdev->irq.hpd[0] = true; | ||
| 126 | break; | ||
| 127 | case RADEON_HPD_2: | ||
| 128 | rdev->irq.hpd[1] = true; | ||
| 129 | break; | ||
| 130 | default: | ||
| 131 | break; | ||
| 132 | } | ||
| 133 | } | ||
| 134 | r100_irq_set(rdev); | ||
| 135 | } | ||
| 136 | |||
| 137 | void r100_hpd_fini(struct radeon_device *rdev) | ||
| 138 | { | ||
| 139 | struct drm_device *dev = rdev->ddev; | ||
| 140 | struct drm_connector *connector; | ||
| 141 | |||
| 142 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { | ||
| 143 | struct radeon_connector *radeon_connector = to_radeon_connector(connector); | ||
| 144 | switch (radeon_connector->hpd.hpd) { | ||
| 145 | case RADEON_HPD_1: | ||
| 146 | rdev->irq.hpd[0] = false; | ||
| 147 | break; | ||
| 148 | case RADEON_HPD_2: | ||
| 149 | rdev->irq.hpd[1] = false; | ||
| 150 | break; | ||
| 151 | default: | ||
| 152 | break; | ||
| 153 | } | ||
| 154 | } | ||
| 155 | } | ||
| 156 | |||
| 68 | /* | 157 | /* |
| 69 | * PCI GART | 158 | * PCI GART |
| 70 | */ | 159 | */ |
| @@ -163,6 +252,12 @@ int r100_irq_set(struct radeon_device *rdev) | |||
| 163 | if (rdev->irq.crtc_vblank_int[1]) { | 252 | if (rdev->irq.crtc_vblank_int[1]) { |
| 164 | tmp |= RADEON_CRTC2_VBLANK_MASK; | 253 | tmp |= RADEON_CRTC2_VBLANK_MASK; |
| 165 | } | 254 | } |
| 255 | if (rdev->irq.hpd[0]) { | ||
| 256 | tmp |= RADEON_FP_DETECT_MASK; | ||
| 257 | } | ||
| 258 | if (rdev->irq.hpd[1]) { | ||
| 259 | tmp |= RADEON_FP2_DETECT_MASK; | ||
| 260 | } | ||
| 166 | WREG32(RADEON_GEN_INT_CNTL, tmp); | 261 | WREG32(RADEON_GEN_INT_CNTL, tmp); |
| 167 | return 0; | 262 | return 0; |
| 168 | } | 263 | } |
| @@ -181,8 +276,9 @@ void r100_irq_disable(struct radeon_device *rdev) | |||
| 181 | static inline uint32_t r100_irq_ack(struct radeon_device *rdev) | 276 | static inline uint32_t r100_irq_ack(struct radeon_device *rdev) |
| 182 | { | 277 | { |
| 183 | uint32_t irqs = RREG32(RADEON_GEN_INT_STATUS); | 278 | uint32_t irqs = RREG32(RADEON_GEN_INT_STATUS); |
| 184 | uint32_t irq_mask = RADEON_SW_INT_TEST | RADEON_CRTC_VBLANK_STAT | | 279 | uint32_t irq_mask = RADEON_SW_INT_TEST | |
| 185 | RADEON_CRTC2_VBLANK_STAT; | 280 | RADEON_CRTC_VBLANK_STAT | RADEON_CRTC2_VBLANK_STAT | |
| 281 | RADEON_FP_DETECT_STAT | RADEON_FP2_DETECT_STAT; | ||
| 186 | 282 | ||
| 187 | if (irqs) { | 283 | if (irqs) { |
| 188 | WREG32(RADEON_GEN_INT_STATUS, irqs); | 284 | WREG32(RADEON_GEN_INT_STATUS, irqs); |
| @@ -213,6 +309,12 @@ int r100_irq_process(struct radeon_device *rdev) | |||
| 213 | if (status & RADEON_CRTC2_VBLANK_STAT) { | 309 | if (status & RADEON_CRTC2_VBLANK_STAT) { |
| 214 | drm_handle_vblank(rdev->ddev, 1); | 310 | drm_handle_vblank(rdev->ddev, 1); |
| 215 | } | 311 | } |
| 312 | if (status & RADEON_FP_DETECT_STAT) { | ||
| 313 | DRM_INFO("HPD1\n"); | ||
| 314 | } | ||
| 315 | if (status & RADEON_FP2_DETECT_STAT) { | ||
| 316 | DRM_INFO("HPD2\n"); | ||
| 317 | } | ||
| 216 | status = r100_irq_ack(rdev); | 318 | status = r100_irq_ack(rdev); |
| 217 | } | 319 | } |
| 218 | if (rdev->msi_enabled) { | 320 | if (rdev->msi_enabled) { |
