diff options
Diffstat (limited to 'drivers/gpu/drm/radeon/r600_cp.c')
-rw-r--r-- | drivers/gpu/drm/radeon/r600_cp.c | 541 |
1 files changed, 388 insertions, 153 deletions
diff --git a/drivers/gpu/drm/radeon/r600_cp.c b/drivers/gpu/drm/radeon/r600_cp.c index 20f17908b036..6d5a711c2e91 100644 --- a/drivers/gpu/drm/radeon/r600_cp.c +++ b/drivers/gpu/drm/radeon/r600_cp.c | |||
@@ -31,7 +31,38 @@ | |||
31 | #include "radeon_drm.h" | 31 | #include "radeon_drm.h" |
32 | #include "radeon_drv.h" | 32 | #include "radeon_drv.h" |
33 | 33 | ||
34 | #include "r600_microcode.h" | 34 | #define PFP_UCODE_SIZE 576 |
35 | #define PM4_UCODE_SIZE 1792 | ||
36 | #define R700_PFP_UCODE_SIZE 848 | ||
37 | #define R700_PM4_UCODE_SIZE 1360 | ||
38 | |||
39 | /* Firmware Names */ | ||
40 | MODULE_FIRMWARE("radeon/R600_pfp.bin"); | ||
41 | MODULE_FIRMWARE("radeon/R600_me.bin"); | ||
42 | MODULE_FIRMWARE("radeon/RV610_pfp.bin"); | ||
43 | MODULE_FIRMWARE("radeon/RV610_me.bin"); | ||
44 | MODULE_FIRMWARE("radeon/RV630_pfp.bin"); | ||
45 | MODULE_FIRMWARE("radeon/RV630_me.bin"); | ||
46 | MODULE_FIRMWARE("radeon/RV620_pfp.bin"); | ||
47 | MODULE_FIRMWARE("radeon/RV620_me.bin"); | ||
48 | MODULE_FIRMWARE("radeon/RV635_pfp.bin"); | ||
49 | MODULE_FIRMWARE("radeon/RV635_me.bin"); | ||
50 | MODULE_FIRMWARE("radeon/RV670_pfp.bin"); | ||
51 | MODULE_FIRMWARE("radeon/RV670_me.bin"); | ||
52 | MODULE_FIRMWARE("radeon/RS780_pfp.bin"); | ||
53 | MODULE_FIRMWARE("radeon/RS780_me.bin"); | ||
54 | MODULE_FIRMWARE("radeon/RV770_pfp.bin"); | ||
55 | MODULE_FIRMWARE("radeon/RV770_me.bin"); | ||
56 | MODULE_FIRMWARE("radeon/RV730_pfp.bin"); | ||
57 | MODULE_FIRMWARE("radeon/RV730_me.bin"); | ||
58 | MODULE_FIRMWARE("radeon/RV710_pfp.bin"); | ||
59 | MODULE_FIRMWARE("radeon/RV710_me.bin"); | ||
60 | |||
61 | |||
62 | int r600_cs_legacy(struct drm_device *dev, void *data, struct drm_file *filp, | ||
63 | unsigned family, u32 *ib, int *l); | ||
64 | void r600_cs_legacy_init(void); | ||
65 | |||
35 | 66 | ||
36 | # define ATI_PCIGART_PAGE_SIZE 4096 /**< PCI GART page size */ | 67 | # define ATI_PCIGART_PAGE_SIZE 4096 /**< PCI GART page size */ |
37 | # define ATI_PCIGART_PAGE_MASK (~(ATI_PCIGART_PAGE_SIZE-1)) | 68 | # define ATI_PCIGART_PAGE_MASK (~(ATI_PCIGART_PAGE_SIZE-1)) |
@@ -275,11 +306,93 @@ static void r600_vm_init(struct drm_device *dev) | |||
275 | r600_vm_flush_gart_range(dev); | 306 | r600_vm_flush_gart_range(dev); |
276 | } | 307 | } |
277 | 308 | ||
278 | /* load r600 microcode */ | 309 | static int r600_cp_init_microcode(drm_radeon_private_t *dev_priv) |
310 | { | ||
311 | struct platform_device *pdev; | ||
312 | const char *chip_name; | ||
313 | size_t pfp_req_size, me_req_size; | ||
314 | char fw_name[30]; | ||
315 | int err; | ||
316 | |||
317 | pdev = platform_device_register_simple("r600_cp", 0, NULL, 0); | ||
318 | err = IS_ERR(pdev); | ||
319 | if (err) { | ||
320 | printk(KERN_ERR "r600_cp: Failed to register firmware\n"); | ||
321 | return -EINVAL; | ||
322 | } | ||
323 | |||
324 | switch (dev_priv->flags & RADEON_FAMILY_MASK) { | ||
325 | case CHIP_R600: chip_name = "R600"; break; | ||
326 | case CHIP_RV610: chip_name = "RV610"; break; | ||
327 | case CHIP_RV630: chip_name = "RV630"; break; | ||
328 | case CHIP_RV620: chip_name = "RV620"; break; | ||
329 | case CHIP_RV635: chip_name = "RV635"; break; | ||
330 | case CHIP_RV670: chip_name = "RV670"; break; | ||
331 | case CHIP_RS780: | ||
332 | case CHIP_RS880: chip_name = "RS780"; break; | ||
333 | case CHIP_RV770: chip_name = "RV770"; break; | ||
334 | case CHIP_RV730: | ||
335 | case CHIP_RV740: chip_name = "RV730"; break; | ||
336 | case CHIP_RV710: chip_name = "RV710"; break; | ||
337 | default: BUG(); | ||
338 | } | ||
339 | |||
340 | if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RV770) { | ||
341 | pfp_req_size = R700_PFP_UCODE_SIZE * 4; | ||
342 | me_req_size = R700_PM4_UCODE_SIZE * 4; | ||
343 | } else { | ||
344 | pfp_req_size = PFP_UCODE_SIZE * 4; | ||
345 | me_req_size = PM4_UCODE_SIZE * 12; | ||
346 | } | ||
347 | |||
348 | DRM_INFO("Loading %s CP Microcode\n", chip_name); | ||
349 | |||
350 | snprintf(fw_name, sizeof(fw_name), "radeon/%s_pfp.bin", chip_name); | ||
351 | err = request_firmware(&dev_priv->pfp_fw, fw_name, &pdev->dev); | ||
352 | if (err) | ||
353 | goto out; | ||
354 | if (dev_priv->pfp_fw->size != pfp_req_size) { | ||
355 | printk(KERN_ERR | ||
356 | "r600_cp: Bogus length %zu in firmware \"%s\"\n", | ||
357 | dev_priv->pfp_fw->size, fw_name); | ||
358 | err = -EINVAL; | ||
359 | goto out; | ||
360 | } | ||
361 | |||
362 | snprintf(fw_name, sizeof(fw_name), "radeon/%s_me.bin", chip_name); | ||
363 | err = request_firmware(&dev_priv->me_fw, fw_name, &pdev->dev); | ||
364 | if (err) | ||
365 | goto out; | ||
366 | if (dev_priv->me_fw->size != me_req_size) { | ||
367 | printk(KERN_ERR | ||
368 | "r600_cp: Bogus length %zu in firmware \"%s\"\n", | ||
369 | dev_priv->me_fw->size, fw_name); | ||
370 | err = -EINVAL; | ||
371 | } | ||
372 | out: | ||
373 | platform_device_unregister(pdev); | ||
374 | |||
375 | if (err) { | ||
376 | if (err != -EINVAL) | ||
377 | printk(KERN_ERR | ||
378 | "r600_cp: Failed to load firmware \"%s\"\n", | ||
379 | fw_name); | ||
380 | release_firmware(dev_priv->pfp_fw); | ||
381 | dev_priv->pfp_fw = NULL; | ||
382 | release_firmware(dev_priv->me_fw); | ||
383 | dev_priv->me_fw = NULL; | ||
384 | } | ||
385 | return err; | ||
386 | } | ||
387 | |||
279 | static void r600_cp_load_microcode(drm_radeon_private_t *dev_priv) | 388 | static void r600_cp_load_microcode(drm_radeon_private_t *dev_priv) |
280 | { | 389 | { |
390 | const __be32 *fw_data; | ||
281 | int i; | 391 | int i; |
282 | 392 | ||
393 | if (!dev_priv->me_fw || !dev_priv->pfp_fw) | ||
394 | return; | ||
395 | |||
283 | r600_do_cp_stop(dev_priv); | 396 | r600_do_cp_stop(dev_priv); |
284 | 397 | ||
285 | RADEON_WRITE(R600_CP_RB_CNTL, | 398 | RADEON_WRITE(R600_CP_RB_CNTL, |
@@ -292,115 +405,18 @@ static void r600_cp_load_microcode(drm_radeon_private_t *dev_priv) | |||
292 | DRM_UDELAY(15000); | 405 | DRM_UDELAY(15000); |
293 | RADEON_WRITE(R600_GRBM_SOFT_RESET, 0); | 406 | RADEON_WRITE(R600_GRBM_SOFT_RESET, 0); |
294 | 407 | ||
408 | fw_data = (const __be32 *)dev_priv->me_fw->data; | ||
295 | RADEON_WRITE(R600_CP_ME_RAM_WADDR, 0); | 409 | RADEON_WRITE(R600_CP_ME_RAM_WADDR, 0); |
410 | for (i = 0; i < PM4_UCODE_SIZE * 3; i++) | ||
411 | RADEON_WRITE(R600_CP_ME_RAM_DATA, | ||
412 | be32_to_cpup(fw_data++)); | ||
296 | 413 | ||
297 | if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R600)) { | 414 | fw_data = (const __be32 *)dev_priv->pfp_fw->data; |
298 | DRM_INFO("Loading R600 CP Microcode\n"); | 415 | RADEON_WRITE(R600_CP_PFP_UCODE_ADDR, 0); |
299 | for (i = 0; i < PM4_UCODE_SIZE; i++) { | 416 | for (i = 0; i < PFP_UCODE_SIZE; i++) |
300 | RADEON_WRITE(R600_CP_ME_RAM_DATA, | 417 | RADEON_WRITE(R600_CP_PFP_UCODE_DATA, |
301 | R600_cp_microcode[i][0]); | 418 | be32_to_cpup(fw_data++)); |
302 | RADEON_WRITE(R600_CP_ME_RAM_DATA, | ||
303 | R600_cp_microcode[i][1]); | ||
304 | RADEON_WRITE(R600_CP_ME_RAM_DATA, | ||
305 | R600_cp_microcode[i][2]); | ||
306 | } | ||
307 | |||
308 | RADEON_WRITE(R600_CP_PFP_UCODE_ADDR, 0); | ||
309 | DRM_INFO("Loading R600 PFP Microcode\n"); | ||
310 | for (i = 0; i < PFP_UCODE_SIZE; i++) | ||
311 | RADEON_WRITE(R600_CP_PFP_UCODE_DATA, R600_pfp_microcode[i]); | ||
312 | } else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV610)) { | ||
313 | DRM_INFO("Loading RV610 CP Microcode\n"); | ||
314 | for (i = 0; i < PM4_UCODE_SIZE; i++) { | ||
315 | RADEON_WRITE(R600_CP_ME_RAM_DATA, | ||
316 | RV610_cp_microcode[i][0]); | ||
317 | RADEON_WRITE(R600_CP_ME_RAM_DATA, | ||
318 | RV610_cp_microcode[i][1]); | ||
319 | RADEON_WRITE(R600_CP_ME_RAM_DATA, | ||
320 | RV610_cp_microcode[i][2]); | ||
321 | } | ||
322 | |||
323 | RADEON_WRITE(R600_CP_PFP_UCODE_ADDR, 0); | ||
324 | DRM_INFO("Loading RV610 PFP Microcode\n"); | ||
325 | for (i = 0; i < PFP_UCODE_SIZE; i++) | ||
326 | RADEON_WRITE(R600_CP_PFP_UCODE_DATA, RV610_pfp_microcode[i]); | ||
327 | } else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV630)) { | ||
328 | DRM_INFO("Loading RV630 CP Microcode\n"); | ||
329 | for (i = 0; i < PM4_UCODE_SIZE; i++) { | ||
330 | RADEON_WRITE(R600_CP_ME_RAM_DATA, | ||
331 | RV630_cp_microcode[i][0]); | ||
332 | RADEON_WRITE(R600_CP_ME_RAM_DATA, | ||
333 | RV630_cp_microcode[i][1]); | ||
334 | RADEON_WRITE(R600_CP_ME_RAM_DATA, | ||
335 | RV630_cp_microcode[i][2]); | ||
336 | } | ||
337 | |||
338 | RADEON_WRITE(R600_CP_PFP_UCODE_ADDR, 0); | ||
339 | DRM_INFO("Loading RV630 PFP Microcode\n"); | ||
340 | for (i = 0; i < PFP_UCODE_SIZE; i++) | ||
341 | RADEON_WRITE(R600_CP_PFP_UCODE_DATA, RV630_pfp_microcode[i]); | ||
342 | } else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV620)) { | ||
343 | DRM_INFO("Loading RV620 CP Microcode\n"); | ||
344 | for (i = 0; i < PM4_UCODE_SIZE; i++) { | ||
345 | RADEON_WRITE(R600_CP_ME_RAM_DATA, | ||
346 | RV620_cp_microcode[i][0]); | ||
347 | RADEON_WRITE(R600_CP_ME_RAM_DATA, | ||
348 | RV620_cp_microcode[i][1]); | ||
349 | RADEON_WRITE(R600_CP_ME_RAM_DATA, | ||
350 | RV620_cp_microcode[i][2]); | ||
351 | } | ||
352 | |||
353 | RADEON_WRITE(R600_CP_PFP_UCODE_ADDR, 0); | ||
354 | DRM_INFO("Loading RV620 PFP Microcode\n"); | ||
355 | for (i = 0; i < PFP_UCODE_SIZE; i++) | ||
356 | RADEON_WRITE(R600_CP_PFP_UCODE_DATA, RV620_pfp_microcode[i]); | ||
357 | } else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV635)) { | ||
358 | DRM_INFO("Loading RV635 CP Microcode\n"); | ||
359 | for (i = 0; i < PM4_UCODE_SIZE; i++) { | ||
360 | RADEON_WRITE(R600_CP_ME_RAM_DATA, | ||
361 | RV635_cp_microcode[i][0]); | ||
362 | RADEON_WRITE(R600_CP_ME_RAM_DATA, | ||
363 | RV635_cp_microcode[i][1]); | ||
364 | RADEON_WRITE(R600_CP_ME_RAM_DATA, | ||
365 | RV635_cp_microcode[i][2]); | ||
366 | } | ||
367 | |||
368 | RADEON_WRITE(R600_CP_PFP_UCODE_ADDR, 0); | ||
369 | DRM_INFO("Loading RV635 PFP Microcode\n"); | ||
370 | for (i = 0; i < PFP_UCODE_SIZE; i++) | ||
371 | RADEON_WRITE(R600_CP_PFP_UCODE_DATA, RV635_pfp_microcode[i]); | ||
372 | } else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV670)) { | ||
373 | DRM_INFO("Loading RV670 CP Microcode\n"); | ||
374 | for (i = 0; i < PM4_UCODE_SIZE; i++) { | ||
375 | RADEON_WRITE(R600_CP_ME_RAM_DATA, | ||
376 | RV670_cp_microcode[i][0]); | ||
377 | RADEON_WRITE(R600_CP_ME_RAM_DATA, | ||
378 | RV670_cp_microcode[i][1]); | ||
379 | RADEON_WRITE(R600_CP_ME_RAM_DATA, | ||
380 | RV670_cp_microcode[i][2]); | ||
381 | } | ||
382 | |||
383 | RADEON_WRITE(R600_CP_PFP_UCODE_ADDR, 0); | ||
384 | DRM_INFO("Loading RV670 PFP Microcode\n"); | ||
385 | for (i = 0; i < PFP_UCODE_SIZE; i++) | ||
386 | RADEON_WRITE(R600_CP_PFP_UCODE_DATA, RV670_pfp_microcode[i]); | ||
387 | } else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS780) || | ||
388 | ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS880)) { | ||
389 | DRM_INFO("Loading RS780/RS880 CP Microcode\n"); | ||
390 | for (i = 0; i < PM4_UCODE_SIZE; i++) { | ||
391 | RADEON_WRITE(R600_CP_ME_RAM_DATA, | ||
392 | RS780_cp_microcode[i][0]); | ||
393 | RADEON_WRITE(R600_CP_ME_RAM_DATA, | ||
394 | RS780_cp_microcode[i][1]); | ||
395 | RADEON_WRITE(R600_CP_ME_RAM_DATA, | ||
396 | RS780_cp_microcode[i][2]); | ||
397 | } | ||
398 | 419 | ||
399 | RADEON_WRITE(R600_CP_PFP_UCODE_ADDR, 0); | ||
400 | DRM_INFO("Loading RS780/RS880 PFP Microcode\n"); | ||
401 | for (i = 0; i < PFP_UCODE_SIZE; i++) | ||
402 | RADEON_WRITE(R600_CP_PFP_UCODE_DATA, RS780_pfp_microcode[i]); | ||
403 | } | ||
404 | RADEON_WRITE(R600_CP_PFP_UCODE_ADDR, 0); | 420 | RADEON_WRITE(R600_CP_PFP_UCODE_ADDR, 0); |
405 | RADEON_WRITE(R600_CP_ME_RAM_WADDR, 0); | 421 | RADEON_WRITE(R600_CP_ME_RAM_WADDR, 0); |
406 | RADEON_WRITE(R600_CP_ME_RAM_RADDR, 0); | 422 | RADEON_WRITE(R600_CP_ME_RAM_RADDR, 0); |
@@ -459,11 +475,14 @@ static void r700_vm_init(struct drm_device *dev) | |||
459 | r600_vm_flush_gart_range(dev); | 475 | r600_vm_flush_gart_range(dev); |
460 | } | 476 | } |
461 | 477 | ||
462 | /* load r600 microcode */ | ||
463 | static void r700_cp_load_microcode(drm_radeon_private_t *dev_priv) | 478 | static void r700_cp_load_microcode(drm_radeon_private_t *dev_priv) |
464 | { | 479 | { |
480 | const __be32 *fw_data; | ||
465 | int i; | 481 | int i; |
466 | 482 | ||
483 | if (!dev_priv->me_fw || !dev_priv->pfp_fw) | ||
484 | return; | ||
485 | |||
467 | r600_do_cp_stop(dev_priv); | 486 | r600_do_cp_stop(dev_priv); |
468 | 487 | ||
469 | RADEON_WRITE(R600_CP_RB_CNTL, | 488 | RADEON_WRITE(R600_CP_RB_CNTL, |
@@ -476,48 +495,18 @@ static void r700_cp_load_microcode(drm_radeon_private_t *dev_priv) | |||
476 | DRM_UDELAY(15000); | 495 | DRM_UDELAY(15000); |
477 | RADEON_WRITE(R600_GRBM_SOFT_RESET, 0); | 496 | RADEON_WRITE(R600_GRBM_SOFT_RESET, 0); |
478 | 497 | ||
498 | fw_data = (const __be32 *)dev_priv->pfp_fw->data; | ||
499 | RADEON_WRITE(R600_CP_PFP_UCODE_ADDR, 0); | ||
500 | for (i = 0; i < R700_PFP_UCODE_SIZE; i++) | ||
501 | RADEON_WRITE(R600_CP_PFP_UCODE_DATA, be32_to_cpup(fw_data++)); | ||
502 | RADEON_WRITE(R600_CP_PFP_UCODE_ADDR, 0); | ||
479 | 503 | ||
480 | if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV770)) { | 504 | fw_data = (const __be32 *)dev_priv->me_fw->data; |
481 | RADEON_WRITE(R600_CP_PFP_UCODE_ADDR, 0); | 505 | RADEON_WRITE(R600_CP_ME_RAM_WADDR, 0); |
482 | DRM_INFO("Loading RV770/RV790 PFP Microcode\n"); | 506 | for (i = 0; i < R700_PM4_UCODE_SIZE; i++) |
483 | for (i = 0; i < R700_PFP_UCODE_SIZE; i++) | 507 | RADEON_WRITE(R600_CP_ME_RAM_DATA, be32_to_cpup(fw_data++)); |
484 | RADEON_WRITE(R600_CP_PFP_UCODE_DATA, RV770_pfp_microcode[i]); | 508 | RADEON_WRITE(R600_CP_ME_RAM_WADDR, 0); |
485 | RADEON_WRITE(R600_CP_PFP_UCODE_ADDR, 0); | ||
486 | |||
487 | RADEON_WRITE(R600_CP_ME_RAM_WADDR, 0); | ||
488 | DRM_INFO("Loading RV770/RV790 CP Microcode\n"); | ||
489 | for (i = 0; i < R700_PM4_UCODE_SIZE; i++) | ||
490 | RADEON_WRITE(R600_CP_ME_RAM_DATA, RV770_cp_microcode[i]); | ||
491 | RADEON_WRITE(R600_CP_ME_RAM_WADDR, 0); | ||
492 | |||
493 | } else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV730) || | ||
494 | ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV740)) { | ||
495 | RADEON_WRITE(R600_CP_PFP_UCODE_ADDR, 0); | ||
496 | DRM_INFO("Loading RV730/RV740 PFP Microcode\n"); | ||
497 | for (i = 0; i < R700_PFP_UCODE_SIZE; i++) | ||
498 | RADEON_WRITE(R600_CP_PFP_UCODE_DATA, RV730_pfp_microcode[i]); | ||
499 | RADEON_WRITE(R600_CP_PFP_UCODE_ADDR, 0); | ||
500 | |||
501 | RADEON_WRITE(R600_CP_ME_RAM_WADDR, 0); | ||
502 | DRM_INFO("Loading RV730/RV740 CP Microcode\n"); | ||
503 | for (i = 0; i < R700_PM4_UCODE_SIZE; i++) | ||
504 | RADEON_WRITE(R600_CP_ME_RAM_DATA, RV730_cp_microcode[i]); | ||
505 | RADEON_WRITE(R600_CP_ME_RAM_WADDR, 0); | ||
506 | |||
507 | } else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV710)) { | ||
508 | RADEON_WRITE(R600_CP_PFP_UCODE_ADDR, 0); | ||
509 | DRM_INFO("Loading RV710 PFP Microcode\n"); | ||
510 | for (i = 0; i < R700_PFP_UCODE_SIZE; i++) | ||
511 | RADEON_WRITE(R600_CP_PFP_UCODE_DATA, RV710_pfp_microcode[i]); | ||
512 | RADEON_WRITE(R600_CP_PFP_UCODE_ADDR, 0); | ||
513 | |||
514 | RADEON_WRITE(R600_CP_ME_RAM_WADDR, 0); | ||
515 | DRM_INFO("Loading RV710 CP Microcode\n"); | ||
516 | for (i = 0; i < R700_PM4_UCODE_SIZE; i++) | ||
517 | RADEON_WRITE(R600_CP_ME_RAM_DATA, RV710_cp_microcode[i]); | ||
518 | RADEON_WRITE(R600_CP_ME_RAM_WADDR, 0); | ||
519 | 509 | ||
520 | } | ||
521 | RADEON_WRITE(R600_CP_PFP_UCODE_ADDR, 0); | 510 | RADEON_WRITE(R600_CP_PFP_UCODE_ADDR, 0); |
522 | RADEON_WRITE(R600_CP_ME_RAM_WADDR, 0); | 511 | RADEON_WRITE(R600_CP_ME_RAM_WADDR, 0); |
523 | RADEON_WRITE(R600_CP_ME_RAM_RADDR, 0); | 512 | RADEON_WRITE(R600_CP_ME_RAM_RADDR, 0); |
@@ -1874,6 +1863,8 @@ int r600_do_init_cp(struct drm_device *dev, drm_radeon_init_t *init, | |||
1874 | 1863 | ||
1875 | DRM_DEBUG("\n"); | 1864 | DRM_DEBUG("\n"); |
1876 | 1865 | ||
1866 | mutex_init(&dev_priv->cs_mutex); | ||
1867 | r600_cs_legacy_init(); | ||
1877 | /* if we require new memory map but we don't have it fail */ | 1868 | /* if we require new memory map but we don't have it fail */ |
1878 | if ((dev_priv->flags & RADEON_NEW_MEMMAP) && !dev_priv->new_memmap) { | 1869 | if ((dev_priv->flags & RADEON_NEW_MEMMAP) && !dev_priv->new_memmap) { |
1879 | DRM_ERROR("Cannot initialise DRM on this card\nThis card requires a new X.org DDX for 3D\n"); | 1870 | DRM_ERROR("Cannot initialise DRM on this card\nThis card requires a new X.org DDX for 3D\n"); |
@@ -1905,7 +1896,7 @@ int r600_do_init_cp(struct drm_device *dev, drm_radeon_init_t *init, | |||
1905 | /* Enable vblank on CRTC1 for older X servers | 1896 | /* Enable vblank on CRTC1 for older X servers |
1906 | */ | 1897 | */ |
1907 | dev_priv->vblank_crtc = DRM_RADEON_VBLANK_CRTC1; | 1898 | dev_priv->vblank_crtc = DRM_RADEON_VBLANK_CRTC1; |
1908 | 1899 | dev_priv->do_boxes = 0; | |
1909 | dev_priv->cp_mode = init->cp_mode; | 1900 | dev_priv->cp_mode = init->cp_mode; |
1910 | 1901 | ||
1911 | /* We don't support anything other than bus-mastering ring mode, | 1902 | /* We don't support anything other than bus-mastering ring mode, |
@@ -1991,11 +1982,11 @@ int r600_do_init_cp(struct drm_device *dev, drm_radeon_init_t *init, | |||
1991 | } else | 1982 | } else |
1992 | #endif | 1983 | #endif |
1993 | { | 1984 | { |
1994 | dev_priv->cp_ring->handle = (void *)dev_priv->cp_ring->offset; | 1985 | dev_priv->cp_ring->handle = (void *)(unsigned long)dev_priv->cp_ring->offset; |
1995 | dev_priv->ring_rptr->handle = | 1986 | dev_priv->ring_rptr->handle = |
1996 | (void *)dev_priv->ring_rptr->offset; | 1987 | (void *)(unsigned long)dev_priv->ring_rptr->offset; |
1997 | dev->agp_buffer_map->handle = | 1988 | dev->agp_buffer_map->handle = |
1998 | (void *)dev->agp_buffer_map->offset; | 1989 | (void *)(unsigned long)dev->agp_buffer_map->offset; |
1999 | 1990 | ||
2000 | DRM_DEBUG("dev_priv->cp_ring->handle %p\n", | 1991 | DRM_DEBUG("dev_priv->cp_ring->handle %p\n", |
2001 | dev_priv->cp_ring->handle); | 1992 | dev_priv->cp_ring->handle); |
@@ -2147,6 +2138,14 @@ int r600_do_init_cp(struct drm_device *dev, drm_radeon_init_t *init, | |||
2147 | r600_vm_init(dev); | 2138 | r600_vm_init(dev); |
2148 | } | 2139 | } |
2149 | 2140 | ||
2141 | if (!dev_priv->me_fw || !dev_priv->pfp_fw) { | ||
2142 | int err = r600_cp_init_microcode(dev_priv); | ||
2143 | if (err) { | ||
2144 | DRM_ERROR("Failed to load firmware!\n"); | ||
2145 | r600_do_cleanup_cp(dev); | ||
2146 | return err; | ||
2147 | } | ||
2148 | } | ||
2150 | if (((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RV770)) | 2149 | if (((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RV770)) |
2151 | r700_cp_load_microcode(dev_priv); | 2150 | r700_cp_load_microcode(dev_priv); |
2152 | else | 2151 | else |
@@ -2291,3 +2290,239 @@ int r600_cp_dispatch_indirect(struct drm_device *dev, | |||
2291 | 2290 | ||
2292 | return 0; | 2291 | return 0; |
2293 | } | 2292 | } |
2293 | |||
2294 | void r600_cp_dispatch_swap(struct drm_device *dev, struct drm_file *file_priv) | ||
2295 | { | ||
2296 | drm_radeon_private_t *dev_priv = dev->dev_private; | ||
2297 | struct drm_master *master = file_priv->master; | ||
2298 | struct drm_radeon_master_private *master_priv = master->driver_priv; | ||
2299 | drm_radeon_sarea_t *sarea_priv = master_priv->sarea_priv; | ||
2300 | int nbox = sarea_priv->nbox; | ||
2301 | struct drm_clip_rect *pbox = sarea_priv->boxes; | ||
2302 | int i, cpp, src_pitch, dst_pitch; | ||
2303 | uint64_t src, dst; | ||
2304 | RING_LOCALS; | ||
2305 | DRM_DEBUG("\n"); | ||
2306 | |||
2307 | if (dev_priv->color_fmt == RADEON_COLOR_FORMAT_ARGB8888) | ||
2308 | cpp = 4; | ||
2309 | else | ||
2310 | cpp = 2; | ||
2311 | |||
2312 | if (sarea_priv->pfCurrentPage == 0) { | ||
2313 | src_pitch = dev_priv->back_pitch; | ||
2314 | dst_pitch = dev_priv->front_pitch; | ||
2315 | src = dev_priv->back_offset + dev_priv->fb_location; | ||
2316 | dst = dev_priv->front_offset + dev_priv->fb_location; | ||
2317 | } else { | ||
2318 | src_pitch = dev_priv->front_pitch; | ||
2319 | dst_pitch = dev_priv->back_pitch; | ||
2320 | src = dev_priv->front_offset + dev_priv->fb_location; | ||
2321 | dst = dev_priv->back_offset + dev_priv->fb_location; | ||
2322 | } | ||
2323 | |||
2324 | if (r600_prepare_blit_copy(dev, file_priv)) { | ||
2325 | DRM_ERROR("unable to allocate vertex buffer for swap buffer\n"); | ||
2326 | return; | ||
2327 | } | ||
2328 | for (i = 0; i < nbox; i++) { | ||
2329 | int x = pbox[i].x1; | ||
2330 | int y = pbox[i].y1; | ||
2331 | int w = pbox[i].x2 - x; | ||
2332 | int h = pbox[i].y2 - y; | ||
2333 | |||
2334 | DRM_DEBUG("%d,%d-%d,%d\n", x, y, w, h); | ||
2335 | |||
2336 | r600_blit_swap(dev, | ||
2337 | src, dst, | ||
2338 | x, y, x, y, w, h, | ||
2339 | src_pitch, dst_pitch, cpp); | ||
2340 | } | ||
2341 | r600_done_blit_copy(dev); | ||
2342 | |||
2343 | /* Increment the frame counter. The client-side 3D driver must | ||
2344 | * throttle the framerate by waiting for this value before | ||
2345 | * performing the swapbuffer ioctl. | ||
2346 | */ | ||
2347 | sarea_priv->last_frame++; | ||
2348 | |||
2349 | BEGIN_RING(3); | ||
2350 | R600_FRAME_AGE(sarea_priv->last_frame); | ||
2351 | ADVANCE_RING(); | ||
2352 | } | ||
2353 | |||
2354 | int r600_cp_dispatch_texture(struct drm_device *dev, | ||
2355 | struct drm_file *file_priv, | ||
2356 | drm_radeon_texture_t *tex, | ||
2357 | drm_radeon_tex_image_t *image) | ||
2358 | { | ||
2359 | drm_radeon_private_t *dev_priv = dev->dev_private; | ||
2360 | struct drm_buf *buf; | ||
2361 | u32 *buffer; | ||
2362 | const u8 __user *data; | ||
2363 | int size, pass_size; | ||
2364 | u64 src_offset, dst_offset; | ||
2365 | |||
2366 | if (!radeon_check_offset(dev_priv, tex->offset)) { | ||
2367 | DRM_ERROR("Invalid destination offset\n"); | ||
2368 | return -EINVAL; | ||
2369 | } | ||
2370 | |||
2371 | /* this might fail for zero-sized uploads - are those illegal? */ | ||
2372 | if (!radeon_check_offset(dev_priv, tex->offset + tex->height * tex->pitch - 1)) { | ||
2373 | DRM_ERROR("Invalid final destination offset\n"); | ||
2374 | return -EINVAL; | ||
2375 | } | ||
2376 | |||
2377 | size = tex->height * tex->pitch; | ||
2378 | |||
2379 | if (size == 0) | ||
2380 | return 0; | ||
2381 | |||
2382 | dst_offset = tex->offset; | ||
2383 | |||
2384 | if (r600_prepare_blit_copy(dev, file_priv)) { | ||
2385 | DRM_ERROR("unable to allocate vertex buffer for swap buffer\n"); | ||
2386 | return -EAGAIN; | ||
2387 | } | ||
2388 | do { | ||
2389 | data = (const u8 __user *)image->data; | ||
2390 | pass_size = size; | ||
2391 | |||
2392 | buf = radeon_freelist_get(dev); | ||
2393 | if (!buf) { | ||
2394 | DRM_DEBUG("EAGAIN\n"); | ||
2395 | if (DRM_COPY_TO_USER(tex->image, image, sizeof(*image))) | ||
2396 | return -EFAULT; | ||
2397 | return -EAGAIN; | ||
2398 | } | ||
2399 | |||
2400 | if (pass_size > buf->total) | ||
2401 | pass_size = buf->total; | ||
2402 | |||
2403 | /* Dispatch the indirect buffer. | ||
2404 | */ | ||
2405 | buffer = | ||
2406 | (u32 *) ((char *)dev->agp_buffer_map->handle + buf->offset); | ||
2407 | |||
2408 | if (DRM_COPY_FROM_USER(buffer, data, pass_size)) { | ||
2409 | DRM_ERROR("EFAULT on pad, %d bytes\n", pass_size); | ||
2410 | return -EFAULT; | ||
2411 | } | ||
2412 | |||
2413 | buf->file_priv = file_priv; | ||
2414 | buf->used = pass_size; | ||
2415 | src_offset = dev_priv->gart_buffers_offset + buf->offset; | ||
2416 | |||
2417 | r600_blit_copy(dev, src_offset, dst_offset, pass_size); | ||
2418 | |||
2419 | radeon_cp_discard_buffer(dev, file_priv->master, buf); | ||
2420 | |||
2421 | /* Update the input parameters for next time */ | ||
2422 | image->data = (const u8 __user *)image->data + pass_size; | ||
2423 | dst_offset += pass_size; | ||
2424 | size -= pass_size; | ||
2425 | } while (size > 0); | ||
2426 | r600_done_blit_copy(dev); | ||
2427 | |||
2428 | return 0; | ||
2429 | } | ||
2430 | |||
2431 | /* | ||
2432 | * Legacy cs ioctl | ||
2433 | */ | ||
2434 | static u32 radeon_cs_id_get(struct drm_radeon_private *radeon) | ||
2435 | { | ||
2436 | /* FIXME: check if wrap affect last reported wrap & sequence */ | ||
2437 | radeon->cs_id_scnt = (radeon->cs_id_scnt + 1) & 0x00FFFFFF; | ||
2438 | if (!radeon->cs_id_scnt) { | ||
2439 | /* increment wrap counter */ | ||
2440 | radeon->cs_id_wcnt += 0x01000000; | ||
2441 | /* valid sequence counter start at 1 */ | ||
2442 | radeon->cs_id_scnt = 1; | ||
2443 | } | ||
2444 | return (radeon->cs_id_scnt | radeon->cs_id_wcnt); | ||
2445 | } | ||
2446 | |||
2447 | static void r600_cs_id_emit(drm_radeon_private_t *dev_priv, u32 *id) | ||
2448 | { | ||
2449 | RING_LOCALS; | ||
2450 | |||
2451 | *id = radeon_cs_id_get(dev_priv); | ||
2452 | |||
2453 | /* SCRATCH 2 */ | ||
2454 | BEGIN_RING(3); | ||
2455 | R600_CLEAR_AGE(*id); | ||
2456 | ADVANCE_RING(); | ||
2457 | COMMIT_RING(); | ||
2458 | } | ||
2459 | |||
2460 | static int r600_ib_get(struct drm_device *dev, | ||
2461 | struct drm_file *fpriv, | ||
2462 | struct drm_buf **buffer) | ||
2463 | { | ||
2464 | struct drm_buf *buf; | ||
2465 | |||
2466 | *buffer = NULL; | ||
2467 | buf = radeon_freelist_get(dev); | ||
2468 | if (!buf) { | ||
2469 | return -EBUSY; | ||
2470 | } | ||
2471 | buf->file_priv = fpriv; | ||
2472 | *buffer = buf; | ||
2473 | return 0; | ||
2474 | } | ||
2475 | |||
2476 | static void r600_ib_free(struct drm_device *dev, struct drm_buf *buf, | ||
2477 | struct drm_file *fpriv, int l, int r) | ||
2478 | { | ||
2479 | drm_radeon_private_t *dev_priv = dev->dev_private; | ||
2480 | |||
2481 | if (buf) { | ||
2482 | if (!r) | ||
2483 | r600_cp_dispatch_indirect(dev, buf, 0, l * 4); | ||
2484 | radeon_cp_discard_buffer(dev, fpriv->master, buf); | ||
2485 | COMMIT_RING(); | ||
2486 | } | ||
2487 | } | ||
2488 | |||
2489 | int r600_cs_legacy_ioctl(struct drm_device *dev, void *data, struct drm_file *fpriv) | ||
2490 | { | ||
2491 | struct drm_radeon_private *dev_priv = dev->dev_private; | ||
2492 | struct drm_radeon_cs *cs = data; | ||
2493 | struct drm_buf *buf; | ||
2494 | unsigned family; | ||
2495 | int l, r = 0; | ||
2496 | u32 *ib, cs_id = 0; | ||
2497 | |||
2498 | if (dev_priv == NULL) { | ||
2499 | DRM_ERROR("called with no initialization\n"); | ||
2500 | return -EINVAL; | ||
2501 | } | ||
2502 | family = dev_priv->flags & RADEON_FAMILY_MASK; | ||
2503 | if (family < CHIP_R600) { | ||
2504 | DRM_ERROR("cs ioctl valid only for R6XX & R7XX in legacy mode\n"); | ||
2505 | return -EINVAL; | ||
2506 | } | ||
2507 | mutex_lock(&dev_priv->cs_mutex); | ||
2508 | /* get ib */ | ||
2509 | r = r600_ib_get(dev, fpriv, &buf); | ||
2510 | if (r) { | ||
2511 | DRM_ERROR("ib_get failed\n"); | ||
2512 | goto out; | ||
2513 | } | ||
2514 | ib = dev->agp_buffer_map->handle + buf->offset; | ||
2515 | /* now parse command stream */ | ||
2516 | r = r600_cs_legacy(dev, data, fpriv, family, ib, &l); | ||
2517 | if (r) { | ||
2518 | goto out; | ||
2519 | } | ||
2520 | |||
2521 | out: | ||
2522 | r600_ib_free(dev, buf, fpriv, l, r); | ||
2523 | /* emit cs id sequence */ | ||
2524 | r600_cs_id_emit(dev_priv, &cs_id); | ||
2525 | cs->cs_id = cs_id; | ||
2526 | mutex_unlock(&dev_priv->cs_mutex); | ||
2527 | return r; | ||
2528 | } | ||