diff options
Diffstat (limited to 'drivers/gpu/drm/radeon/radeon_kms.c')
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_kms.c | 108 |
1 files changed, 89 insertions, 19 deletions
diff --git a/drivers/gpu/drm/radeon/radeon_kms.c b/drivers/gpu/drm/radeon/radeon_kms.c index 8fbbe1c6ebbd..bd58af658581 100644 --- a/drivers/gpu/drm/radeon/radeon_kms.c +++ b/drivers/gpu/drm/radeon/radeon_kms.c | |||
@@ -58,9 +58,9 @@ int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags) | |||
58 | dev->dev_private = (void *)rdev; | 58 | dev->dev_private = (void *)rdev; |
59 | 59 | ||
60 | /* update BUS flag */ | 60 | /* update BUS flag */ |
61 | if (drm_device_is_agp(dev)) { | 61 | if (drm_pci_device_is_agp(dev)) { |
62 | flags |= RADEON_IS_AGP; | 62 | flags |= RADEON_IS_AGP; |
63 | } else if (drm_device_is_pcie(dev)) { | 63 | } else if (drm_pci_device_is_pcie(dev)) { |
64 | flags |= RADEON_IS_PCIE; | 64 | flags |= RADEON_IS_PCIE; |
65 | } else { | 65 | } else { |
66 | flags |= RADEON_IS_PCI; | 66 | flags |= RADEON_IS_PCI; |
@@ -96,9 +96,27 @@ out: | |||
96 | return r; | 96 | return r; |
97 | } | 97 | } |
98 | 98 | ||
99 | static void radeon_set_filp_rights(struct drm_device *dev, | ||
100 | struct drm_file **owner, | ||
101 | struct drm_file *applier, | ||
102 | uint32_t *value) | ||
103 | { | ||
104 | mutex_lock(&dev->struct_mutex); | ||
105 | if (*value == 1) { | ||
106 | /* wants rights */ | ||
107 | if (!*owner) | ||
108 | *owner = applier; | ||
109 | } else if (*value == 0) { | ||
110 | /* revokes rights */ | ||
111 | if (*owner == applier) | ||
112 | *owner = NULL; | ||
113 | } | ||
114 | *value = *owner == applier ? 1 : 0; | ||
115 | mutex_unlock(&dev->struct_mutex); | ||
116 | } | ||
99 | 117 | ||
100 | /* | 118 | /* |
101 | * Userspace get informations ioctl | 119 | * Userspace get information ioctl |
102 | */ | 120 | */ |
103 | int radeon_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) | 121 | int radeon_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) |
104 | { | 122 | { |
@@ -151,7 +169,9 @@ int radeon_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) | |||
151 | value = rdev->accel_working; | 169 | value = rdev->accel_working; |
152 | break; | 170 | break; |
153 | case RADEON_INFO_TILING_CONFIG: | 171 | case RADEON_INFO_TILING_CONFIG: |
154 | if (rdev->family >= CHIP_CEDAR) | 172 | if (rdev->family >= CHIP_CAYMAN) |
173 | value = rdev->config.cayman.tile_config; | ||
174 | else if (rdev->family >= CHIP_CEDAR) | ||
155 | value = rdev->config.evergreen.tile_config; | 175 | value = rdev->config.evergreen.tile_config; |
156 | else if (rdev->family >= CHIP_RV770) | 176 | else if (rdev->family >= CHIP_RV770) |
157 | value = rdev->config.rv770.tile_config; | 177 | value = rdev->config.rv770.tile_config; |
@@ -173,18 +193,49 @@ int radeon_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) | |||
173 | DRM_DEBUG_KMS("WANT_HYPERZ: invalid value %d\n", value); | 193 | DRM_DEBUG_KMS("WANT_HYPERZ: invalid value %d\n", value); |
174 | return -EINVAL; | 194 | return -EINVAL; |
175 | } | 195 | } |
176 | mutex_lock(&dev->struct_mutex); | 196 | radeon_set_filp_rights(dev, &rdev->hyperz_filp, filp, &value); |
177 | if (value == 1) { | 197 | break; |
178 | /* wants hyper-z */ | 198 | case RADEON_INFO_WANT_CMASK: |
179 | if (!rdev->hyperz_filp) | 199 | /* The same logic as Hyper-Z. */ |
180 | rdev->hyperz_filp = filp; | 200 | if (value >= 2) { |
181 | } else if (value == 0) { | 201 | DRM_DEBUG_KMS("WANT_CMASK: invalid value %d\n", value); |
182 | /* revokes hyper-z */ | 202 | return -EINVAL; |
183 | if (rdev->hyperz_filp == filp) | 203 | } |
184 | rdev->hyperz_filp = NULL; | 204 | radeon_set_filp_rights(dev, &rdev->cmask_filp, filp, &value); |
205 | break; | ||
206 | case RADEON_INFO_CLOCK_CRYSTAL_FREQ: | ||
207 | /* return clock value in KHz */ | ||
208 | value = rdev->clock.spll.reference_freq * 10; | ||
209 | break; | ||
210 | case RADEON_INFO_NUM_BACKENDS: | ||
211 | if (rdev->family >= CHIP_CAYMAN) | ||
212 | value = rdev->config.cayman.max_backends_per_se * | ||
213 | rdev->config.cayman.max_shader_engines; | ||
214 | else if (rdev->family >= CHIP_CEDAR) | ||
215 | value = rdev->config.evergreen.max_backends; | ||
216 | else if (rdev->family >= CHIP_RV770) | ||
217 | value = rdev->config.rv770.max_backends; | ||
218 | else if (rdev->family >= CHIP_R600) | ||
219 | value = rdev->config.r600.max_backends; | ||
220 | else { | ||
221 | return -EINVAL; | ||
222 | } | ||
223 | break; | ||
224 | case RADEON_INFO_NUM_TILE_PIPES: | ||
225 | if (rdev->family >= CHIP_CAYMAN) | ||
226 | value = rdev->config.cayman.max_tile_pipes; | ||
227 | else if (rdev->family >= CHIP_CEDAR) | ||
228 | value = rdev->config.evergreen.max_tile_pipes; | ||
229 | else if (rdev->family >= CHIP_RV770) | ||
230 | value = rdev->config.rv770.max_tile_pipes; | ||
231 | else if (rdev->family >= CHIP_R600) | ||
232 | value = rdev->config.r600.max_tile_pipes; | ||
233 | else { | ||
234 | return -EINVAL; | ||
185 | } | 235 | } |
186 | value = rdev->hyperz_filp == filp ? 1 : 0; | 236 | break; |
187 | mutex_unlock(&dev->struct_mutex); | 237 | case RADEON_INFO_FUSION_GART_WORKING: |
238 | value = 1; | ||
188 | break; | 239 | break; |
189 | default: | 240 | default: |
190 | DRM_DEBUG_KMS("Invalid request %d\n", info->request); | 241 | DRM_DEBUG_KMS("Invalid request %d\n", info->request); |
@@ -203,10 +254,6 @@ int radeon_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) | |||
203 | */ | 254 | */ |
204 | int radeon_driver_firstopen_kms(struct drm_device *dev) | 255 | int radeon_driver_firstopen_kms(struct drm_device *dev) |
205 | { | 256 | { |
206 | struct radeon_device *rdev = dev->dev_private; | ||
207 | |||
208 | if (rdev->powered_down) | ||
209 | return -EINVAL; | ||
210 | return 0; | 257 | return 0; |
211 | } | 258 | } |
212 | 259 | ||
@@ -232,6 +279,8 @@ void radeon_driver_preclose_kms(struct drm_device *dev, | |||
232 | struct radeon_device *rdev = dev->dev_private; | 279 | struct radeon_device *rdev = dev->dev_private; |
233 | if (rdev->hyperz_filp == file_priv) | 280 | if (rdev->hyperz_filp == file_priv) |
234 | rdev->hyperz_filp = NULL; | 281 | rdev->hyperz_filp = NULL; |
282 | if (rdev->cmask_filp == file_priv) | ||
283 | rdev->cmask_filp = NULL; | ||
235 | } | 284 | } |
236 | 285 | ||
237 | /* | 286 | /* |
@@ -277,6 +326,27 @@ void radeon_disable_vblank_kms(struct drm_device *dev, int crtc) | |||
277 | radeon_irq_set(rdev); | 326 | radeon_irq_set(rdev); |
278 | } | 327 | } |
279 | 328 | ||
329 | int radeon_get_vblank_timestamp_kms(struct drm_device *dev, int crtc, | ||
330 | int *max_error, | ||
331 | struct timeval *vblank_time, | ||
332 | unsigned flags) | ||
333 | { | ||
334 | struct drm_crtc *drmcrtc; | ||
335 | struct radeon_device *rdev = dev->dev_private; | ||
336 | |||
337 | if (crtc < 0 || crtc >= dev->num_crtcs) { | ||
338 | DRM_ERROR("Invalid crtc %d\n", crtc); | ||
339 | return -EINVAL; | ||
340 | } | ||
341 | |||
342 | /* Get associated drm_crtc: */ | ||
343 | drmcrtc = &rdev->mode_info.crtcs[crtc]->base; | ||
344 | |||
345 | /* Helper routine in DRM core does all the work: */ | ||
346 | return drm_calc_vbltimestamp_from_scanoutpos(dev, crtc, max_error, | ||
347 | vblank_time, flags, | ||
348 | drmcrtc); | ||
349 | } | ||
280 | 350 | ||
281 | /* | 351 | /* |
282 | * IOCTL. | 352 | * IOCTL. |