radeon_kms.c 28.0 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
/*
 * Copyright 2008 Advanced Micro Devices, Inc.
 * Copyright 2008 Red Hat Inc.
 * Copyright 2009 Jerome Glisse.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 * OTHER DEALINGS IN THE SOFTWARE.
 *
 * Authors: Dave Airlie
 *          Alex Deucher
 *          Jerome Glisse
 */
28
#include <drm/drmP.h>
29
#include "radeon.h"
30
#include <drm/radeon_drm.h>
31
#include "radeon_asic.h"
32

33
#include <linux/vga_switcheroo.h>
34
#include <linux/slab.h>
35
#include <linux/pm_runtime.h>
36

37 38
#include "radeon_kfd.h"

39
#if defined(CONFIG_VGA_SWITCHEROO)
40
bool radeon_has_atpx(void);
41
#else
42
static inline bool radeon_has_atpx(void) { return false; }
43 44
#endif

A
Alex Deucher 已提交
45 46 47 48 49 50 51 52 53 54 55
/**
 * radeon_driver_unload_kms - Main unload function for KMS.
 *
 * @dev: drm dev pointer
 *
 * This is the main unload function for KMS (all asics).
 * It calls radeon_modeset_fini() to tear down the
 * displays, and radeon_device_fini() to tear down
 * the rest of the device (CP, writeback, etc.).
 * Returns 0 on success.
 */
56 57 58 59 60 61
int radeon_driver_unload_kms(struct drm_device *dev)
{
	struct radeon_device *rdev = dev->dev_private;

	if (rdev == NULL)
		return 0;
62

63 64
	if (rdev->rmmio == NULL)
		goto done_free;
65 66 67

	pm_runtime_get_sync(dev->dev);

68 69
	radeon_kfd_device_fini(rdev);

70
	radeon_acpi_fini(rdev);
71
	
72 73
	radeon_modeset_fini(rdev);
	radeon_device_fini(rdev);
74 75

done_free:
76 77 78 79
	kfree(rdev);
	dev->dev_private = NULL;
	return 0;
}
80

A
Alex Deucher 已提交
81 82 83 84 85 86 87 88 89 90 91 92 93
/**
 * radeon_driver_load_kms - Main load function for KMS.
 *
 * @dev: drm dev pointer
 * @flags: device flags
 *
 * This is the main load function for KMS (all asics).
 * It calls radeon_device_init() to set up the non-display
 * parts of the chip (asic init, CP, writeback, etc.), and
 * radeon_modeset_init() to set up the display parts
 * (crtcs, encoders, hotplug detect, etc.).
 * Returns 0 on success, error on failure.
 */
94 95 96
int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags)
{
	struct radeon_device *rdev;
97
	int r, acpi_status;
98 99 100 101 102 103 104 105

	rdev = kzalloc(sizeof(struct radeon_device), GFP_KERNEL);
	if (rdev == NULL) {
		return -ENOMEM;
	}
	dev->dev_private = (void *)rdev;

	/* update BUS flag */
106
	if (drm_pci_device_is_agp(dev)) {
107
		flags |= RADEON_IS_AGP;
J
Jon Mason 已提交
108
	} else if (pci_is_pcie(dev->pdev)) {
109 110 111 112 113
		flags |= RADEON_IS_PCIE;
	} else {
		flags |= RADEON_IS_PCI;
	}

114 115 116
	if ((radeon_runtime_pm != 0) &&
	    radeon_has_atpx() &&
	    ((flags & RADEON_IS_IGP) == 0))
117 118
		flags |= RADEON_IS_PX;

119 120 121 122 123 124
	/* radeon_device_init should report only fatal error
	 * like memory allocation failure or iomapping failure,
	 * or memory manager initialization failure, it must
	 * properly initialize the GPU MC controller and permit
	 * VRAM allocation
	 */
125 126
	r = radeon_device_init(rdev, dev, dev->pdev, flags);
	if (r) {
127 128
		dev_err(&dev->pdev->dev, "Fatal error during GPU init\n");
		goto out;
129
	}
130

131 132 133 134 135
	/* Again modeset_init should fail only on fatal error
	 * otherwise it should provide enough functionalities
	 * for shadowfb to run
	 */
	r = radeon_modeset_init(rdev);
136 137
	if (r)
		dev_err(&dev->pdev->dev, "Fatal error during modeset init\n");
138 139 140 141 142 143 144 145 146 147 148

	/* Call ACPI methods: require modeset init
	 * but failure is not fatal
	 */
	if (!r) {
		acpi_status = radeon_acpi_init(rdev);
		if (acpi_status)
		dev_dbg(&dev->pdev->dev,
				"Error during ACPI methods call\n");
	}

149 150 151
	radeon_kfd_device_probe(rdev);
	radeon_kfd_device_init(rdev);

152
	if (radeon_is_px(dev)) {
153 154 155 156 157 158 159 160
		pm_runtime_use_autosuspend(dev->dev);
		pm_runtime_set_autosuspend_delay(dev->dev, 5000);
		pm_runtime_set_active(dev->dev);
		pm_runtime_allow(dev->dev);
		pm_runtime_mark_last_busy(dev->dev);
		pm_runtime_put_autosuspend(dev->dev);
	}

161 162 163
out:
	if (r)
		radeon_driver_unload_kms(dev);
164 165


166
	return r;
167 168
}

A
Alex Deucher 已提交
169 170 171 172 173 174 175 176 177 178
/**
 * radeon_set_filp_rights - Set filp right.
 *
 * @dev: drm dev pointer
 * @owner: drm file
 * @applier: drm file
 * @value: value
 *
 * Sets the filp rights for the device (all asics).
 */
179 180 181 182 183
static void radeon_set_filp_rights(struct drm_device *dev,
				   struct drm_file **owner,
				   struct drm_file *applier,
				   uint32_t *value)
{
184 185 186
	struct radeon_device *rdev = dev->dev_private;

	mutex_lock(&rdev->gem.mutex);
187 188 189 190 191 192 193 194 195 196
	if (*value == 1) {
		/* wants rights */
		if (!*owner)
			*owner = applier;
	} else if (*value == 0) {
		/* revokes rights */
		if (*owner == applier)
			*owner = NULL;
	}
	*value = *owner == applier ? 1 : 0;
197
	mutex_unlock(&rdev->gem.mutex);
198
}
199 200

/*
201
 * Userspace get information ioctl
202
 */
A
Alex Deucher 已提交
203 204 205 206 207 208 209 210 211 212 213 214
/**
 * radeon_info_ioctl - answer a device specific request.
 *
 * @rdev: radeon device pointer
 * @data: request object
 * @filp: drm filp
 *
 * This function is used to pass device specific parameters to the userspace
 * drivers.  Examples include: pci device id, pipeline parms, tiling params,
 * etc. (all asics).
 * Returns 0 on success, -EINVAL on failure.
 */
215
static int radeon_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
216 217
{
	struct radeon_device *rdev = dev->dev_private;
218
	struct drm_radeon_info *info = data;
219
	struct radeon_mode_info *minfo = &rdev->mode_info;
220 221
	uint32_t *value, value_tmp, *value_ptr, value_size;
	uint64_t value64;
222 223
	struct drm_crtc *crtc;
	int i, found;
224 225

	value_ptr = (uint32_t *)((unsigned long)info->value);
226 227
	value = &value_tmp;
	value_size = sizeof(uint32_t);
228

229 230
	switch (info->request) {
	case RADEON_INFO_DEVICE_ID:
231
		*value = dev->pdev->device;
232 233
		break;
	case RADEON_INFO_NUM_GB_PIPES:
234
		*value = rdev->num_gb_pipes;
235
		break;
236
	case RADEON_INFO_NUM_Z_PIPES:
237
		*value = rdev->num_z_pipes;
238
		break;
239
	case RADEON_INFO_ACCEL_WORKING:
240 241
		/* xf86-video-ati 6.13.0 relies on this being false for evergreen */
		if ((rdev->family >= CHIP_CEDAR) && (rdev->family <= CHIP_HEMLOCK))
242
			*value = false;
243
		else
244
			*value = rdev->accel_working;
245
		break;
246
	case RADEON_INFO_CRTC_FROM_ID:
D
Daniel Vetter 已提交
247
		if (copy_from_user(value, value_ptr, sizeof(uint32_t))) {
248 249 250
			DRM_ERROR("copy_from_user %s:%u\n", __func__, __LINE__);
			return -EFAULT;
		}
251 252
		for (i = 0, found = 0; i < rdev->num_crtc; i++) {
			crtc = (struct drm_crtc *)minfo->crtcs[i];
253
			if (crtc && crtc->base.id == *value) {
254
				struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
255
				*value = radeon_crtc->crtc_id;
256 257 258 259 260
				found = 1;
				break;
			}
		}
		if (!found) {
261
			DRM_DEBUG_KMS("unknown crtc id %d\n", *value);
262 263 264
			return -EINVAL;
		}
		break;
265
	case RADEON_INFO_ACCEL_WORKING2:
266
		if (rdev->family == CHIP_HAWAII) {
267 268 269 270 271 272
			if (rdev->accel_working) {
				if (rdev->new_fw)
					*value = 3;
				else
					*value = 2;
			} else {
273
				*value = 0;
274
			}
275 276 277
		} else {
			*value = rdev->accel_working;
		}
278
		break;
279
	case RADEON_INFO_TILING_CONFIG:
280 281 282
		if (rdev->family >= CHIP_BONAIRE)
			*value = rdev->config.cik.tile_config;
		else if (rdev->family >= CHIP_TAHITI)
283
			*value = rdev->config.si.tile_config;
284
		else if (rdev->family >= CHIP_CAYMAN)
285
			*value = rdev->config.cayman.tile_config;
286
		else if (rdev->family >= CHIP_CEDAR)
287
			*value = rdev->config.evergreen.tile_config;
288
		else if (rdev->family >= CHIP_RV770)
289
			*value = rdev->config.rv770.tile_config;
290
		else if (rdev->family >= CHIP_R600)
291
			*value = rdev->config.r600.tile_config;
292
		else {
293
			DRM_DEBUG_KMS("tiling config is r6xx+ only!\n");
294 295
			return -EINVAL;
		}
296
		break;
297
	case RADEON_INFO_WANT_HYPERZ:
298 299 300 301 302 303
		/* The "value" here is both an input and output parameter.
		 * If the input value is 1, filp requests hyper-z access.
		 * If the input value is 0, filp revokes its hyper-z access.
		 *
		 * When returning, the value is 1 if filp owns hyper-z access,
		 * 0 otherwise. */
D
Daniel Vetter 已提交
304
		if (copy_from_user(value, value_ptr, sizeof(uint32_t))) {
305 306 307 308 309
			DRM_ERROR("copy_from_user %s:%u\n", __func__, __LINE__);
			return -EFAULT;
		}
		if (*value >= 2) {
			DRM_DEBUG_KMS("WANT_HYPERZ: invalid value %d\n", *value);
310 311
			return -EINVAL;
		}
312
		radeon_set_filp_rights(dev, &rdev->hyperz_filp, filp, value);
313 314 315
		break;
	case RADEON_INFO_WANT_CMASK:
		/* The same logic as Hyper-Z. */
D
Daniel Vetter 已提交
316
		if (copy_from_user(value, value_ptr, sizeof(uint32_t))) {
317 318 319 320 321
			DRM_ERROR("copy_from_user %s:%u\n", __func__, __LINE__);
			return -EFAULT;
		}
		if (*value >= 2) {
			DRM_DEBUG_KMS("WANT_CMASK: invalid value %d\n", *value);
322
			return -EINVAL;
323
		}
324
		radeon_set_filp_rights(dev, &rdev->cmask_filp, filp, value);
325
		break;
326 327
	case RADEON_INFO_CLOCK_CRYSTAL_FREQ:
		/* return clock value in KHz */
328
		if (rdev->asic->get_xclk)
329
			*value = radeon_get_xclk(rdev) * 10;
330
		else
331
			*value = rdev->clock.spll.reference_freq * 10;
332
		break;
333
	case RADEON_INFO_NUM_BACKENDS:
334 335 336 337
		if (rdev->family >= CHIP_BONAIRE)
			*value = rdev->config.cik.max_backends_per_se *
				rdev->config.cik.max_shader_engines;
		else if (rdev->family >= CHIP_TAHITI)
338
			*value = rdev->config.si.max_backends_per_se *
339 340
				rdev->config.si.max_shader_engines;
		else if (rdev->family >= CHIP_CAYMAN)
341
			*value = rdev->config.cayman.max_backends_per_se *
342 343
				rdev->config.cayman.max_shader_engines;
		else if (rdev->family >= CHIP_CEDAR)
344
			*value = rdev->config.evergreen.max_backends;
345
		else if (rdev->family >= CHIP_RV770)
346
			*value = rdev->config.rv770.max_backends;
347
		else if (rdev->family >= CHIP_R600)
348
			*value = rdev->config.r600.max_backends;
349 350 351 352
		else {
			return -EINVAL;
		}
		break;
353
	case RADEON_INFO_NUM_TILE_PIPES:
354 355 356
		if (rdev->family >= CHIP_BONAIRE)
			*value = rdev->config.cik.max_tile_pipes;
		else if (rdev->family >= CHIP_TAHITI)
357
			*value = rdev->config.si.max_tile_pipes;
358
		else if (rdev->family >= CHIP_CAYMAN)
359
			*value = rdev->config.cayman.max_tile_pipes;
360
		else if (rdev->family >= CHIP_CEDAR)
361
			*value = rdev->config.evergreen.max_tile_pipes;
362
		else if (rdev->family >= CHIP_RV770)
363
			*value = rdev->config.rv770.max_tile_pipes;
364
		else if (rdev->family >= CHIP_R600)
365
			*value = rdev->config.r600.max_tile_pipes;
366 367 368 369
		else {
			return -EINVAL;
		}
		break;
370
	case RADEON_INFO_FUSION_GART_WORKING:
371
		*value = 1;
372
		break;
373
	case RADEON_INFO_BACKEND_MAP:
374
		if (rdev->family >= CHIP_BONAIRE)
375
			*value = rdev->config.cik.backend_map;
376
		else if (rdev->family >= CHIP_TAHITI)
377
			*value = rdev->config.si.backend_map;
378
		else if (rdev->family >= CHIP_CAYMAN)
379
			*value = rdev->config.cayman.backend_map;
380
		else if (rdev->family >= CHIP_CEDAR)
381
			*value = rdev->config.evergreen.backend_map;
382
		else if (rdev->family >= CHIP_RV770)
383
			*value = rdev->config.rv770.backend_map;
384
		else if (rdev->family >= CHIP_R600)
385
			*value = rdev->config.r600.backend_map;
386 387 388 389
		else {
			return -EINVAL;
		}
		break;
390 391 392 393
	case RADEON_INFO_VA_START:
		/* this is where we report if vm is supported or not */
		if (rdev->family < CHIP_CAYMAN)
			return -EINVAL;
394
		*value = RADEON_VA_RESERVED_SIZE;
395 396 397 398 399
		break;
	case RADEON_INFO_IB_VM_MAX_SIZE:
		/* this is where we report if vm is supported or not */
		if (rdev->family < CHIP_CAYMAN)
			return -EINVAL;
400
		*value = RADEON_IB_VM_MAX_SIZE;
401
		break;
402
	case RADEON_INFO_MAX_PIPES:
403 404 405
		if (rdev->family >= CHIP_BONAIRE)
			*value = rdev->config.cik.max_cu_per_sh;
		else if (rdev->family >= CHIP_TAHITI)
406
			*value = rdev->config.si.max_cu_per_sh;
407
		else if (rdev->family >= CHIP_CAYMAN)
408
			*value = rdev->config.cayman.max_pipes_per_simd;
409
		else if (rdev->family >= CHIP_CEDAR)
410
			*value = rdev->config.evergreen.max_pipes;
411
		else if (rdev->family >= CHIP_RV770)
412
			*value = rdev->config.rv770.max_pipes;
413
		else if (rdev->family >= CHIP_R600)
414
			*value = rdev->config.r600.max_pipes;
415 416 417 418
		else {
			return -EINVAL;
		}
		break;
419 420 421 422 423 424 425 426 427
	case RADEON_INFO_TIMESTAMP:
		if (rdev->family < CHIP_R600) {
			DRM_DEBUG_KMS("timestamp is r6xx+ only!\n");
			return -EINVAL;
		}
		value = (uint32_t*)&value64;
		value_size = sizeof(uint64_t);
		value64 = radeon_get_gpu_clock_counter(rdev);
		break;
428
	case RADEON_INFO_MAX_SE:
429 430 431
		if (rdev->family >= CHIP_BONAIRE)
			*value = rdev->config.cik.max_shader_engines;
		else if (rdev->family >= CHIP_TAHITI)
432
			*value = rdev->config.si.max_shader_engines;
433
		else if (rdev->family >= CHIP_CAYMAN)
434
			*value = rdev->config.cayman.max_shader_engines;
435
		else if (rdev->family >= CHIP_CEDAR)
436
			*value = rdev->config.evergreen.num_ses;
437
		else
438
			*value = 1;
439 440
		break;
	case RADEON_INFO_MAX_SH_PER_SE:
441 442 443
		if (rdev->family >= CHIP_BONAIRE)
			*value = rdev->config.cik.max_sh_per_se;
		else if (rdev->family >= CHIP_TAHITI)
444
			*value = rdev->config.si.max_sh_per_se;
445 446 447
		else
			return -EINVAL;
		break;
448
	case RADEON_INFO_FASTFB_WORKING:
449
		*value = rdev->fastfb_working;
450
		break;
451
	case RADEON_INFO_RING_WORKING:
D
Daniel Vetter 已提交
452
		if (copy_from_user(value, value_ptr, sizeof(uint32_t))) {
453 454 455 456
			DRM_ERROR("copy_from_user %s:%u\n", __func__, __LINE__);
			return -EFAULT;
		}
		switch (*value) {
457 458
		case RADEON_CS_RING_GFX:
		case RADEON_CS_RING_COMPUTE:
459
			*value = rdev->ring[RADEON_RING_TYPE_GFX_INDEX].ready;
460 461
			break;
		case RADEON_CS_RING_DMA:
462 463
			*value = rdev->ring[R600_RING_TYPE_DMA_INDEX].ready;
			*value |= rdev->ring[CAYMAN_RING_TYPE_DMA1_INDEX].ready;
464 465
			break;
		case RADEON_CS_RING_UVD:
466
			*value = rdev->ring[R600_RING_TYPE_UVD_INDEX].ready;
467
			break;
468 469 470
		case RADEON_CS_RING_VCE:
			*value = rdev->ring[TN_RING_TYPE_VCE1_INDEX].ready;
			break;
471 472 473 474
		default:
			return -EINVAL;
		}
		break;
475
	case RADEON_INFO_SI_TILE_MODE_ARRAY:
476
		if (rdev->family >= CHIP_BONAIRE) {
477 478 479 480 481 482 483
			value = rdev->config.cik.tile_mode_array;
			value_size = sizeof(uint32_t)*32;
		} else if (rdev->family >= CHIP_TAHITI) {
			value = rdev->config.si.tile_mode_array;
			value_size = sizeof(uint32_t)*32;
		} else {
			DRM_DEBUG_KMS("tile mode array is si+ only!\n");
484 485
			return -EINVAL;
		}
486
		break;
487 488 489 490 491 492 493 494 495
	case RADEON_INFO_CIK_MACROTILE_MODE_ARRAY:
		if (rdev->family >= CHIP_BONAIRE) {
			value = rdev->config.cik.macrotile_mode_array;
			value_size = sizeof(uint32_t)*16;
		} else {
			DRM_DEBUG_KMS("macrotile mode array is cik+ only!\n");
			return -EINVAL;
		}
		break;
496 497 498
	case RADEON_INFO_SI_CP_DMA_COMPUTE:
		*value = 1;
		break;
499 500 501 502 503 504 505 506 507
	case RADEON_INFO_SI_BACKEND_ENABLED_MASK:
		if (rdev->family >= CHIP_BONAIRE) {
			*value = rdev->config.cik.backend_enable_mask;
		} else if (rdev->family >= CHIP_TAHITI) {
			*value = rdev->config.si.backend_enable_mask;
		} else {
			DRM_DEBUG_KMS("BACKEND_ENABLED_MASK is si+ only!\n");
		}
		break;
508 509 510 511 512 513 514
	case RADEON_INFO_MAX_SCLK:
		if ((rdev->pm.pm_method == PM_METHOD_DPM) &&
		    rdev->pm.dpm_enabled)
			*value = rdev->pm.dpm.dyn_state.max_clock_voltage_on_ac.sclk * 10;
		else
			*value = rdev->pm.default_sclk * 10;
		break;
515 516 517 518 519 520
	case RADEON_INFO_VCE_FW_VERSION:
		*value = rdev->vce.fw_version;
		break;
	case RADEON_INFO_VCE_FB_VERSION:
		*value = rdev->vce.fb_version;
		break;
521 522 523 524 525 526 527 528 529 530 531 532 533 534 535
	case RADEON_INFO_NUM_BYTES_MOVED:
		value = (uint32_t*)&value64;
		value_size = sizeof(uint64_t);
		value64 = atomic64_read(&rdev->num_bytes_moved);
		break;
	case RADEON_INFO_VRAM_USAGE:
		value = (uint32_t*)&value64;
		value_size = sizeof(uint64_t);
		value64 = atomic64_read(&rdev->vram_usage);
		break;
	case RADEON_INFO_GTT_USAGE:
		value = (uint32_t*)&value64;
		value_size = sizeof(uint64_t);
		value64 = atomic64_read(&rdev->gtt_usage);
		break;
536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551
	case RADEON_INFO_ACTIVE_CU_COUNT:
		if (rdev->family >= CHIP_BONAIRE)
			*value = rdev->config.cik.active_cus;
		else if (rdev->family >= CHIP_TAHITI)
			*value = rdev->config.si.active_cus;
		else if (rdev->family >= CHIP_CAYMAN)
			*value = rdev->config.cayman.active_simds;
		else if (rdev->family >= CHIP_CEDAR)
			*value = rdev->config.evergreen.active_simds;
		else if (rdev->family >= CHIP_RV770)
			*value = rdev->config.rv770.active_simds;
		else if (rdev->family >= CHIP_R600)
			*value = rdev->config.r600.active_simds;
		else
			*value = 1;
		break;
552 553 554 555 556 557 558
	case RADEON_INFO_CURRENT_GPU_TEMP:
		/* get temperature in millidegrees C */
		if (rdev->asic->pm.get_temperature)
			*value = radeon_get_temperature(rdev);
		else
			*value = 0;
		break;
559 560 561 562 563 564 565 566 567 568 569 570 571 572
	case RADEON_INFO_CURRENT_GPU_SCLK:
		/* get sclk in Mhz */
		if (rdev->pm.dpm_enabled)
			*value = radeon_dpm_get_current_sclk(rdev) / 100;
		else
			*value = rdev->pm.current_sclk / 100;
		break;
	case RADEON_INFO_CURRENT_GPU_MCLK:
		/* get mclk in Mhz */
		if (rdev->pm.dpm_enabled)
			*value = radeon_dpm_get_current_mclk(rdev) / 100;
		else
			*value = rdev->pm.current_mclk / 100;
		break;
573 574 575 576 577 578 579 580
	case RADEON_INFO_READ_REG:
		if (copy_from_user(value, value_ptr, sizeof(uint32_t))) {
			DRM_ERROR("copy_from_user %s:%u\n", __func__, __LINE__);
			return -EFAULT;
		}
		if (radeon_get_allowed_info_register(rdev, *value, value))
			return -EINVAL;
		break;
581 582 583
	case RADEON_INFO_VA_UNMAP_WORKING:
		*value = true;
		break;
584 585 586
	case RADEON_INFO_GPU_RESET_COUNTER:
		*value = atomic_read(&rdev->gpu_reset_counter);
		break;
587
	default:
588
		DRM_DEBUG_KMS("Invalid request %d\n", info->request);
589 590
		return -EINVAL;
	}
D
Daniel Vetter 已提交
591
	if (copy_to_user(value_ptr, (char*)value, value_size)) {
592
		DRM_ERROR("copy_to_user %s:%u\n", __func__, __LINE__);
593 594 595 596 597 598 599 600 601
		return -EFAULT;
	}
	return 0;
}


/*
 * Outdated mess for old drm with Xorg being in charge (void function now).
 */
A
Alex Deucher 已提交
602
/**
603
 * radeon_driver_lastclose_kms - drm callback for last close
A
Alex Deucher 已提交
604 605 606
 *
 * @dev: drm dev pointer
 *
607
 * Switch vga_switcheroo state after last close (all asics).
A
Alex Deucher 已提交
608
 */
609 610
void radeon_driver_lastclose_kms(struct drm_device *dev)
{
611 612 613
	struct radeon_device *rdev = dev->dev_private;

	radeon_fbdev_restore_mode(rdev);
614
	vga_switcheroo_process_delayed_switch();
615 616
}

A
Alex Deucher 已提交
617 618 619 620 621 622 623 624 625
/**
 * radeon_driver_open_kms - drm callback for open
 *
 * @dev: drm dev pointer
 * @file_priv: drm file
 *
 * On device open, init vm on cayman+ (all asics).
 * Returns 0 on success, error on failure.
 */
626 627
int radeon_driver_open_kms(struct drm_device *dev, struct drm_file *file_priv)
{
628
	struct radeon_device *rdev = dev->dev_private;
629
	int r;
630 631 632

	file_priv->driver_priv = NULL;

633 634 635 636
	r = pm_runtime_get_sync(dev->dev);
	if (r < 0)
		return r;

637 638 639
	/* new gpu have virtual address space support */
	if (rdev->family >= CHIP_CAYMAN) {
		struct radeon_fpriv *fpriv;
640
		struct radeon_vm *vm;
641 642 643 644 645 646 647
		int r;

		fpriv = kzalloc(sizeof(*fpriv), GFP_KERNEL);
		if (unlikely(!fpriv)) {
			return -ENOMEM;
		}

648
		if (rdev->accel_working) {
649 650 651 652 653 654 655
			vm = &fpriv->vm;
			r = radeon_vm_init(rdev, vm);
			if (r) {
				kfree(fpriv);
				return r;
			}

656 657
			r = radeon_bo_reserve(rdev->ring_tmp_bo.bo, false);
			if (r) {
658
				radeon_vm_fini(rdev, vm);
659 660 661
				kfree(fpriv);
				return r;
			}
662

663 664
			/* map the ib pool buffer read only into
			 * virtual address space */
665 666 667 668
			vm->ib_bo_va = radeon_vm_bo_add(rdev, vm,
							rdev->ring_tmp_bo.bo);
			r = radeon_vm_bo_set_addr(rdev, vm->ib_bo_va,
						  RADEON_VA_IB_OFFSET,
669 670 671
						  RADEON_VM_PAGE_READABLE |
						  RADEON_VM_PAGE_SNOOPED);
			if (r) {
672
				radeon_vm_fini(rdev, vm);
673 674 675
				kfree(fpriv);
				return r;
			}
676 677 678
		}
		file_priv->driver_priv = fpriv;
	}
679 680 681

	pm_runtime_mark_last_busy(dev->dev);
	pm_runtime_put_autosuspend(dev->dev);
682 683 684
	return 0;
}

A
Alex Deucher 已提交
685 686 687 688 689 690 691 692
/**
 * radeon_driver_postclose_kms - drm callback for post close
 *
 * @dev: drm dev pointer
 * @file_priv: drm file
 *
 * On device post close, tear down vm on cayman+ (all asics).
 */
693 694 695
void radeon_driver_postclose_kms(struct drm_device *dev,
				 struct drm_file *file_priv)
{
696 697 698 699 700
	struct radeon_device *rdev = dev->dev_private;

	/* new gpu have virtual address space support */
	if (rdev->family >= CHIP_CAYMAN && file_priv->driver_priv) {
		struct radeon_fpriv *fpriv = file_priv->driver_priv;
701
		struct radeon_vm *vm = &fpriv->vm;
702 703
		int r;

704 705 706
		if (rdev->accel_working) {
			r = radeon_bo_reserve(rdev->ring_tmp_bo.bo, false);
			if (!r) {
707 708
				if (vm->ib_bo_va)
					radeon_vm_bo_rmv(rdev, vm->ib_bo_va);
709 710
				radeon_bo_unreserve(rdev->ring_tmp_bo.bo);
			}
711
			radeon_vm_fini(rdev, vm);
712
		}
713 714 715 716

		kfree(fpriv);
		file_priv->driver_priv = NULL;
	}
717 718
}

A
Alex Deucher 已提交
719 720 721 722 723 724 725 726 727
/**
 * radeon_driver_preclose_kms - drm callback for pre close
 *
 * @dev: drm dev pointer
 * @file_priv: drm file
 *
 * On device pre close, tear down hyperz and cmask filps on r1xx-r5xx
 * (all asics).
 */
728 729 730
void radeon_driver_preclose_kms(struct drm_device *dev,
				struct drm_file *file_priv)
{
731
	struct radeon_device *rdev = dev->dev_private;
732 733

	mutex_lock(&rdev->gem.mutex);
734 735
	if (rdev->hyperz_filp == file_priv)
		rdev->hyperz_filp = NULL;
736 737
	if (rdev->cmask_filp == file_priv)
		rdev->cmask_filp = NULL;
738 739
	mutex_unlock(&rdev->gem.mutex);

C
Christian König 已提交
740
	radeon_uvd_free_handles(rdev, file_priv);
741
	radeon_vce_free_handles(rdev, file_priv);
742 743 744 745 746
}

/*
 * VBlank related functions.
 */
A
Alex Deucher 已提交
747 748 749 750 751 752 753 754 755
/**
 * radeon_get_vblank_counter_kms - get frame count
 *
 * @dev: drm dev pointer
 * @crtc: crtc to get the frame count from
 *
 * Gets the frame count on the requested crtc (all asics).
 * Returns frame count on success, -EINVAL on failure.
 */
756 757
u32 radeon_get_vblank_counter_kms(struct drm_device *dev, int crtc)
{
758 759
	int vpos, hpos, stat;
	u32 count;
760 761
	struct radeon_device *rdev = dev->dev_private;

762
	if (crtc < 0 || crtc >= rdev->num_crtc) {
763 764 765 766
		DRM_ERROR("Invalid crtc %d\n", crtc);
		return -EINVAL;
	}

767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813
	/* The hw increments its frame counter at start of vsync, not at start
	 * of vblank, as is required by DRM core vblank counter handling.
	 * Cook the hw count here to make it appear to the caller as if it
	 * incremented at start of vblank. We measure distance to start of
	 * vblank in vpos. vpos therefore will be >= 0 between start of vblank
	 * and start of vsync, so vpos >= 0 means to bump the hw frame counter
	 * result by 1 to give the proper appearance to caller.
	 */
	if (rdev->mode_info.crtcs[crtc]) {
		/* Repeat readout if needed to provide stable result if
		 * we cross start of vsync during the queries.
		 */
		do {
			count = radeon_get_vblank_counter(rdev, crtc);
			/* Ask radeon_get_crtc_scanoutpos to return vpos as
			 * distance to start of vblank, instead of regular
			 * vertical scanout pos.
			 */
			stat = radeon_get_crtc_scanoutpos(
				dev, crtc, GET_DISTANCE_TO_VBLANKSTART,
				&vpos, &hpos, NULL, NULL,
				&rdev->mode_info.crtcs[crtc]->base.hwmode);
		} while (count != radeon_get_vblank_counter(rdev, crtc));

		if (((stat & (DRM_SCANOUTPOS_VALID | DRM_SCANOUTPOS_ACCURATE)) !=
		    (DRM_SCANOUTPOS_VALID | DRM_SCANOUTPOS_ACCURATE))) {
			DRM_DEBUG_VBL("Query failed! stat %d\n", stat);
		}
		else {
			DRM_DEBUG_VBL("crtc %d: dist from vblank start %d\n",
				      crtc, vpos);

			/* Bump counter if we are at >= leading edge of vblank,
			 * but before vsync where vpos would turn negative and
			 * the hw counter really increments.
			 */
			if (vpos >= 0)
				count++;
		}
	}
	else {
	    /* Fallback to use value as is. */
	    count = radeon_get_vblank_counter(rdev, crtc);
	    DRM_DEBUG_VBL("NULL mode info! Returned count may be wrong.\n");
	}

	return count;
814 815
}

A
Alex Deucher 已提交
816 817 818 819 820 821 822 823 824
/**
 * radeon_enable_vblank_kms - enable vblank interrupt
 *
 * @dev: drm dev pointer
 * @crtc: crtc to enable vblank interrupt for
 *
 * Enable the interrupt on the requested crtc (all asics).
 * Returns 0 on success, -EINVAL on failure.
 */
825 826
int radeon_enable_vblank_kms(struct drm_device *dev, int crtc)
{
827
	struct radeon_device *rdev = dev->dev_private;
828 829
	unsigned long irqflags;
	int r;
830

831
	if (crtc < 0 || crtc >= rdev->num_crtc) {
832 833 834 835
		DRM_ERROR("Invalid crtc %d\n", crtc);
		return -EINVAL;
	}

836
	spin_lock_irqsave(&rdev->irq.lock, irqflags);
837
	rdev->irq.crtc_vblank_int[crtc] = true;
838 839 840
	r = radeon_irq_set(rdev);
	spin_unlock_irqrestore(&rdev->irq.lock, irqflags);
	return r;
841 842
}

A
Alex Deucher 已提交
843 844 845 846 847 848 849 850
/**
 * radeon_disable_vblank_kms - disable vblank interrupt
 *
 * @dev: drm dev pointer
 * @crtc: crtc to disable vblank interrupt for
 *
 * Disable the interrupt on the requested crtc (all asics).
 */
851 852
void radeon_disable_vblank_kms(struct drm_device *dev, int crtc)
{
853
	struct radeon_device *rdev = dev->dev_private;
854
	unsigned long irqflags;
855

856
	if (crtc < 0 || crtc >= rdev->num_crtc) {
857 858 859 860
		DRM_ERROR("Invalid crtc %d\n", crtc);
		return;
	}

861
	spin_lock_irqsave(&rdev->irq.lock, irqflags);
862 863
	rdev->irq.crtc_vblank_int[crtc] = false;
	radeon_irq_set(rdev);
864
	spin_unlock_irqrestore(&rdev->irq.lock, irqflags);
865 866
}

A
Alex Deucher 已提交
867 868 869 870 871 872 873 874 875 876 877 878 879
/**
 * radeon_get_vblank_timestamp_kms - get vblank timestamp
 *
 * @dev: drm dev pointer
 * @crtc: crtc to get the timestamp for
 * @max_error: max error
 * @vblank_time: time value
 * @flags: flags passed to the driver
 *
 * Gets the timestamp on the requested crtc based on the
 * scanout position.  (all asics).
 * Returns postive status flags on success, negative error on failure.
 */
880 881 882 883 884 885 886 887 888 889 890 891 892 893 894
int radeon_get_vblank_timestamp_kms(struct drm_device *dev, int crtc,
				    int *max_error,
				    struct timeval *vblank_time,
				    unsigned flags)
{
	struct drm_crtc *drmcrtc;
	struct radeon_device *rdev = dev->dev_private;

	if (crtc < 0 || crtc >= dev->num_crtcs) {
		DRM_ERROR("Invalid crtc %d\n", crtc);
		return -EINVAL;
	}

	/* Get associated drm_crtc: */
	drmcrtc = &rdev->mode_info.crtcs[crtc]->base;
895 896
	if (!drmcrtc)
		return -EINVAL;
897 898 899 900

	/* Helper routine in DRM core does all the work: */
	return drm_calc_vbltimestamp_from_scanoutpos(dev, crtc, max_error,
						     vblank_time, flags,
901
						     &drmcrtc->hwmode);
902
}
903

R
Rob Clark 已提交
904
const struct drm_ioctl_desc radeon_ioctls_kms[] = {
905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931
	DRM_IOCTL_DEF_DRV(RADEON_CP_INIT, drm_invalid_op, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
	DRM_IOCTL_DEF_DRV(RADEON_CP_START, drm_invalid_op, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
	DRM_IOCTL_DEF_DRV(RADEON_CP_STOP, drm_invalid_op, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
	DRM_IOCTL_DEF_DRV(RADEON_CP_RESET, drm_invalid_op, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
	DRM_IOCTL_DEF_DRV(RADEON_CP_IDLE, drm_invalid_op, DRM_AUTH),
	DRM_IOCTL_DEF_DRV(RADEON_CP_RESUME, drm_invalid_op, DRM_AUTH),
	DRM_IOCTL_DEF_DRV(RADEON_RESET, drm_invalid_op, DRM_AUTH),
	DRM_IOCTL_DEF_DRV(RADEON_FULLSCREEN, drm_invalid_op, DRM_AUTH),
	DRM_IOCTL_DEF_DRV(RADEON_SWAP, drm_invalid_op, DRM_AUTH),
	DRM_IOCTL_DEF_DRV(RADEON_CLEAR, drm_invalid_op, DRM_AUTH),
	DRM_IOCTL_DEF_DRV(RADEON_VERTEX, drm_invalid_op, DRM_AUTH),
	DRM_IOCTL_DEF_DRV(RADEON_INDICES, drm_invalid_op, DRM_AUTH),
	DRM_IOCTL_DEF_DRV(RADEON_TEXTURE, drm_invalid_op, DRM_AUTH),
	DRM_IOCTL_DEF_DRV(RADEON_STIPPLE, drm_invalid_op, DRM_AUTH),
	DRM_IOCTL_DEF_DRV(RADEON_INDIRECT, drm_invalid_op, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
	DRM_IOCTL_DEF_DRV(RADEON_VERTEX2, drm_invalid_op, DRM_AUTH),
	DRM_IOCTL_DEF_DRV(RADEON_CMDBUF, drm_invalid_op, DRM_AUTH),
	DRM_IOCTL_DEF_DRV(RADEON_GETPARAM, drm_invalid_op, DRM_AUTH),
	DRM_IOCTL_DEF_DRV(RADEON_FLIP, drm_invalid_op, DRM_AUTH),
	DRM_IOCTL_DEF_DRV(RADEON_ALLOC, drm_invalid_op, DRM_AUTH),
	DRM_IOCTL_DEF_DRV(RADEON_FREE, drm_invalid_op, DRM_AUTH),
	DRM_IOCTL_DEF_DRV(RADEON_INIT_HEAP, drm_invalid_op, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
	DRM_IOCTL_DEF_DRV(RADEON_IRQ_EMIT, drm_invalid_op, DRM_AUTH),
	DRM_IOCTL_DEF_DRV(RADEON_IRQ_WAIT, drm_invalid_op, DRM_AUTH),
	DRM_IOCTL_DEF_DRV(RADEON_SETPARAM, drm_invalid_op, DRM_AUTH),
	DRM_IOCTL_DEF_DRV(RADEON_SURF_ALLOC, drm_invalid_op, DRM_AUTH),
	DRM_IOCTL_DEF_DRV(RADEON_SURF_FREE, drm_invalid_op, DRM_AUTH),
932
	/* KMS */
933 934 935 936 937 938 939 940 941 942 943 944 945 946 947
	DRM_IOCTL_DEF_DRV(RADEON_GEM_INFO, radeon_gem_info_ioctl, DRM_AUTH|DRM_RENDER_ALLOW),
	DRM_IOCTL_DEF_DRV(RADEON_GEM_CREATE, radeon_gem_create_ioctl, DRM_AUTH|DRM_RENDER_ALLOW),
	DRM_IOCTL_DEF_DRV(RADEON_GEM_MMAP, radeon_gem_mmap_ioctl, DRM_AUTH|DRM_RENDER_ALLOW),
	DRM_IOCTL_DEF_DRV(RADEON_GEM_SET_DOMAIN, radeon_gem_set_domain_ioctl, DRM_AUTH|DRM_RENDER_ALLOW),
	DRM_IOCTL_DEF_DRV(RADEON_GEM_PREAD, radeon_gem_pread_ioctl, DRM_AUTH),
	DRM_IOCTL_DEF_DRV(RADEON_GEM_PWRITE, radeon_gem_pwrite_ioctl, DRM_AUTH),
	DRM_IOCTL_DEF_DRV(RADEON_GEM_WAIT_IDLE, radeon_gem_wait_idle_ioctl, DRM_AUTH|DRM_RENDER_ALLOW),
	DRM_IOCTL_DEF_DRV(RADEON_CS, radeon_cs_ioctl, DRM_AUTH|DRM_RENDER_ALLOW),
	DRM_IOCTL_DEF_DRV(RADEON_INFO, radeon_info_ioctl, DRM_AUTH|DRM_RENDER_ALLOW),
	DRM_IOCTL_DEF_DRV(RADEON_GEM_SET_TILING, radeon_gem_set_tiling_ioctl, DRM_AUTH|DRM_RENDER_ALLOW),
	DRM_IOCTL_DEF_DRV(RADEON_GEM_GET_TILING, radeon_gem_get_tiling_ioctl, DRM_AUTH|DRM_RENDER_ALLOW),
	DRM_IOCTL_DEF_DRV(RADEON_GEM_BUSY, radeon_gem_busy_ioctl, DRM_AUTH|DRM_RENDER_ALLOW),
	DRM_IOCTL_DEF_DRV(RADEON_GEM_VA, radeon_gem_va_ioctl, DRM_AUTH|DRM_RENDER_ALLOW),
	DRM_IOCTL_DEF_DRV(RADEON_GEM_OP, radeon_gem_op_ioctl, DRM_AUTH|DRM_RENDER_ALLOW),
	DRM_IOCTL_DEF_DRV(RADEON_GEM_USERPTR, radeon_gem_userptr_ioctl, DRM_AUTH|DRM_RENDER_ALLOW),
948
};
949
int radeon_max_kms_ioctl = ARRAY_SIZE(radeon_ioctls_kms);