diff options
author | Alex Deucher <alexdeucher@gmail.com> | 2009-12-04 15:04:19 -0500 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2009-12-07 19:47:58 -0500 |
commit | dcfdd4083509f9c46b1e92c58c062d50da50580e (patch) | |
tree | 3d6c6fe080491e3a3848390652dab7c9234469cd /drivers | |
parent | 05a05c506f52041daa511f4899b63d21c9457474 (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')
-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) { |