nouveau_agp.c 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. #include <linux/module.h>
  2. #include <core/device.h>
  3. #include "nouveau_drm.h"
  4. #include "nouveau_agp.h"
  5. #include "nouveau_reg.h"
  6. #if __OS_HAS_AGP
  7. MODULE_PARM_DESC(agpmode, "AGP mode (0 to disable AGP)");
  8. static int nouveau_agpmode = -1;
  9. module_param_named(agpmode, nouveau_agpmode, int, 0400);
  10. static unsigned long
  11. get_agp_mode(struct nouveau_drm *drm, unsigned long mode)
  12. {
  13. struct nouveau_device *device = nv_device(drm->device);
  14. /*
  15. * FW seems to be broken on nv18, it makes the card lock up
  16. * randomly.
  17. */
  18. if (device->chipset == 0x18)
  19. mode &= ~PCI_AGP_COMMAND_FW;
  20. /*
  21. * AGP mode set in the command line.
  22. */
  23. if (nouveau_agpmode > 0) {
  24. bool agpv3 = mode & 0x8;
  25. int rate = agpv3 ? nouveau_agpmode / 4 : nouveau_agpmode;
  26. mode = (mode & ~0x7) | (rate & 0x7);
  27. }
  28. return mode;
  29. }
  30. static bool
  31. nouveau_agp_enabled(struct nouveau_drm *drm)
  32. {
  33. struct drm_device *dev = drm->dev;
  34. if (!drm_pci_device_is_agp(dev) || !dev->agp)
  35. return false;
  36. if (drm->agp.stat == UNKNOWN) {
  37. if (!nouveau_agpmode)
  38. return false;
  39. return true;
  40. }
  41. return (drm->agp.stat == ENABLED);
  42. }
  43. #endif
  44. void
  45. nouveau_agp_reset(struct nouveau_drm *drm)
  46. {
  47. #if __OS_HAS_AGP
  48. struct nouveau_device *device = nv_device(drm->device);
  49. struct drm_device *dev = drm->dev;
  50. u32 save[2];
  51. int ret;
  52. if (!nouveau_agp_enabled(drm))
  53. return;
  54. /* First of all, disable fast writes, otherwise if it's
  55. * already enabled in the AGP bridge and we disable the card's
  56. * AGP controller we might be locking ourselves out of it. */
  57. if ((nv_rd32(device, NV04_PBUS_PCI_NV_19) |
  58. dev->agp->mode) & PCI_AGP_COMMAND_FW) {
  59. struct drm_agp_info info;
  60. struct drm_agp_mode mode;
  61. ret = drm_agp_info(dev, &info);
  62. if (ret)
  63. return;
  64. mode.mode = get_agp_mode(drm, info.mode);
  65. mode.mode &= ~PCI_AGP_COMMAND_FW;
  66. ret = drm_agp_enable(dev, mode);
  67. if (ret)
  68. return;
  69. }
  70. /* clear busmaster bit, and disable AGP */
  71. save[0] = nv_mask(device, NV04_PBUS_PCI_NV_1, 0x00000004, 0x00000000);
  72. nv_wr32(device, NV04_PBUS_PCI_NV_19, 0);
  73. /* reset PGRAPH, PFIFO and PTIMER */
  74. save[1] = nv_mask(device, 0x000200, 0x00011100, 0x00000000);
  75. nv_mask(device, 0x000200, 0x00011100, save[1]);
  76. /* and restore bustmaster bit (gives effect of resetting AGP) */
  77. nv_wr32(device, NV04_PBUS_PCI_NV_1, save[0]);
  78. #endif
  79. }
  80. void
  81. nouveau_agp_init(struct nouveau_drm *drm)
  82. {
  83. #if __OS_HAS_AGP
  84. struct nouveau_device *device = nv_device(drm->device);
  85. struct drm_device *dev = drm->dev;
  86. struct drm_agp_info info;
  87. struct drm_agp_mode mode;
  88. int ret;
  89. if (!nouveau_agp_enabled(drm))
  90. return;
  91. drm->agp.stat = DISABLE;
  92. ret = drm_agp_acquire(dev);
  93. if (ret) {
  94. nv_error(device, "unable to acquire AGP: %d\n", ret);
  95. return;
  96. }
  97. ret = drm_agp_info(dev, &info);
  98. if (ret) {
  99. nv_error(device, "unable to get AGP info: %d\n", ret);
  100. return;
  101. }
  102. /* see agp.h for the AGPSTAT_* modes available */
  103. mode.mode = get_agp_mode(drm, info.mode);
  104. ret = drm_agp_enable(dev, mode);
  105. if (ret) {
  106. nv_error(device, "unable to enable AGP: %d\n", ret);
  107. return;
  108. }
  109. drm->agp.stat = ENABLED;
  110. drm->agp.base = info.aperture_base;
  111. drm->agp.size = info.aperture_size;
  112. #endif
  113. }
  114. void
  115. nouveau_agp_fini(struct nouveau_drm *drm)
  116. {
  117. #if __OS_HAS_AGP
  118. struct drm_device *dev = drm->dev;
  119. if (dev->agp && dev->agp->acquired)
  120. drm_agp_release(dev);
  121. #endif
  122. }