diff options
author | Alex Deucher <alexdeucher@gmail.com> | 2009-12-04 14:53:41 -0500 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2009-12-07 19:46:38 -0500 |
commit | 05a05c506f52041daa511f4899b63d21c9457474 (patch) | |
tree | 00336d311cc7ef14421c0dddb17f468b2de48375 | |
parent | b500f68045058454549f5f8553110ef086d8d06b (diff) |
drm/radeon/kms: add hpd support for r1xx-r4xx 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>
-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) { |