aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/radeon/rs600.c
diff options
context:
space:
mode:
authorAlex Deucher <alexdeucher@gmail.com>2009-12-04 15:04:19 -0500
committerDave Airlie <airlied@redhat.com>2009-12-07 19:47:58 -0500
commitdcfdd4083509f9c46b1e92c58c062d50da50580e (patch)
tree3d6c6fe080491e3a3848390652dab7c9234469cd /drivers/gpu/drm/radeon/rs600.c
parent05a05c506f52041daa511f4899b63d21c9457474 (diff)
drm/radeon/kms: add hpd support for r5xx/rs600/rs690/rs740 asics
This just adds the functionality, it's not hooked up yet. Signed-off-by: Alex Deucher <alexdeucher@gmail.com> Signed-off-by: Dave Airlie <airlied@redhat.com>
Diffstat (limited to 'drivers/gpu/drm/radeon/rs600.c')
-rw-r--r--drivers/gpu/drm/radeon/rs600.c130
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 */
65bool 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
87void 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
115void 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
140void 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) {