2 #include "nv_include.h"
5 void NVDmaKickoff(NVPtr pNv)
7 if(pNv->dmaCurrent != pNv->dmaPut) {
8 pNv->dmaPut = pNv->dmaCurrent;
9 WRITE_PUT(pNv, pNv->dmaPut);
13 void NVDmaKickoffCallback(NVPtr pNv)
16 pNv->DMAKickoffCallback = NULL;
19 static uint32_t subchannels[8];
21 void NVDmaStart(NVPtr pNv, uint32_t object, uint32_t tag, int size)
27 ScrnInfoPtr pScrn = xf86Screens[0];
29 /* look for a subchannel already bound to that object */
32 if (subchannels[i]==object)
39 /* add 2 for the potential subchannel binding */
40 if((pNv)->dmaFree <= (size + 2))
41 NVDmaWait(pScrn, size + 2);
47 subchannels[subchannel]=object;
48 NVDEBUG("Bind object %x on subchannel %d\n", (object), (subchannel));
49 NVDmaNext(pNv, (1<<18) | (subchannel<<13));
50 NVDmaNext(pNv,object);
53 NVDEBUG("NVDmaStart: subc=%d, cmd=%x, num=%d\n", (subchannel), (tag), (size));
54 NVDmaNext(pNv, ((size) << 18) | ((subchannel) << 13) | (tag));
55 pNv->dmaFree -= ((size) + 1);
59 /* There is a HW race condition with videoram command buffers.
60 * You can't jump to the location of your put offset. We write put
61 * at the jump offset + SKIPS dwords with noop padding in between
62 * to solve this problem
66 void NVDmaWait (ScrnInfoPtr pScrn, int size)
68 NVPtr pNv = NVPTR(pScrn);
74 t_start = GetTimeInMillis();
75 while(pNv->dmaFree < size) {
76 dmaGet = READ_GET(pNv);
78 if(pNv->dmaPut >= dmaGet) {
79 pNv->dmaFree = pNv->dmaMax - pNv->dmaCurrent;
80 if(pNv->dmaFree < size) {
81 NVDmaNext(pNv, (0x20000000|pNv->fifo.put_base));
83 if(pNv->dmaPut <= SKIPS) /* corner case - will be idle */
84 WRITE_PUT(pNv, SKIPS + 1);
86 if (GetTimeInMillis() - t_start > 2000)
88 dmaGet = READ_GET(pNv);
89 } while(dmaGet <= SKIPS);
91 WRITE_PUT(pNv, SKIPS);
92 pNv->dmaCurrent = pNv->dmaPut = SKIPS;
93 pNv->dmaFree = dmaGet - (SKIPS + 1);
96 pNv->dmaFree = dmaGet - pNv->dmaCurrent - 1;
98 if (GetTimeInMillis() - t_start > 2000)
103 static void NVDumpLockupInfo(NVPtr pNv)
106 start=READ_GET(pNv)-20;
107 if (start<0) start=0;
108 xf86DrvMsg(0, X_INFO, "Fifo dump (lockup 0x%04x,0x%04x):\n",READ_GET(pNv),pNv->dmaPut);
109 for(i=start;i<pNv->dmaPut+10;i++)
110 xf86DrvMsg(0, X_INFO, "[0x%04x] 0x%08x\n", i, pNv->dmaBase[i]);
111 xf86DrvMsg(0, X_INFO, "End of fifo dump\n");
115 NVLockedUp(ScrnInfoPtr pScrn)
117 NVPtr pNv = NVPTR(pScrn);
119 /* avoid re-entering FatalError on shutdown */
122 pNv->LockedUp = TRUE;
124 NVDumpLockupInfo(pNv);
126 FatalError("DMA queue hang: dmaPut=%x, current=%x, status=%x\n",
127 pNv->dmaPut, READ_GET(pNv), pNv->PGRAPH[NV_PGRAPH_STATUS/4]);
130 void NVSync(ScrnInfoPtr pScrn)
132 NVPtr pNv = NVPTR(pScrn);
133 int t_start, timeout = 2000;
134 int grobj = pNv->Architecture < NV_ARCH_50 ? NvImageBlit : Nv2D;
139 if(pNv->DMAKickoffCallback)
140 (*pNv->DMAKickoffCallback)(pNv);
142 /* Wait for entire FIFO to be processed */
143 t_start = GetTimeInMillis();
144 while((GetTimeInMillis() - t_start) < timeout &&
145 (READ_GET(pNv) != pNv->dmaPut));
146 if ((GetTimeInMillis() - t_start) >= timeout) {
151 /* Wait for channel to go completely idle */
152 NVNotifierReset(pScrn, pNv->Notifier0);
153 NVDmaStart(pNv, grobj, 0x104, 1);
155 NVDmaStart(pNv, grobj, 0x100, 1);
158 if (!NVNotifierWaitStatus(pScrn, pNv->Notifier0, 0, timeout))
162 void NVResetGraphics(ScrnInfoPtr pScrn)
164 NVPtr pNv = NVPTR(pScrn);
165 CARD32 surfaceFormat, patternFormat, rectFormat, lineFormat;
168 if(pNv->NoAccel) return;
170 pitch = pNv->CurrentLayout.displayWidth * (pNv->CurrentLayout.bitsPerPixel >> 3);
172 pNv->dmaPut = pNv->dmaCurrent = READ_GET(pNv);
173 pNv->dmaMax = (pNv->fifo.cmdbuf_size >> 2) - 2;
174 pNv->dmaFree = pNv->dmaMax - pNv->dmaCurrent;
176 /* assert there's enough room for the skips */
177 if(pNv->dmaFree <= SKIPS)
178 NVDmaWait(pScrn, SKIPS);
179 for (i=0; i<SKIPS; i++) {
183 pNv->dmaFree -= SKIPS;
188 NVAccelCommonInit(pScrn);
190 if (pNv->Architecture >= NV_ARCH_50)
193 switch(pNv->CurrentLayout.depth) {
195 surfaceFormat = SURFACE_FORMAT_X8R8G8B8;
196 patternFormat = PATTERN_FORMAT_DEPTH24;
197 rectFormat = RECT_FORMAT_DEPTH24;
198 lineFormat = LINE_FORMAT_DEPTH24;
202 surfaceFormat = SURFACE_FORMAT_R5G6B5;
203 patternFormat = PATTERN_FORMAT_DEPTH16;
204 rectFormat = RECT_FORMAT_DEPTH16;
205 lineFormat = LINE_FORMAT_DEPTH16;
208 surfaceFormat = SURFACE_FORMAT_Y8;
209 patternFormat = PATTERN_FORMAT_DEPTH8;
210 rectFormat = RECT_FORMAT_DEPTH8;
211 lineFormat = LINE_FORMAT_DEPTH8;
215 NVDmaStart(pNv, NvContextSurfaces, SURFACE_FORMAT, 4);
216 NVDmaNext (pNv, surfaceFormat);
217 NVDmaNext (pNv, pitch | (pitch << 16));
218 NVDmaNext (pNv, (uint32_t)pNv->FB->offset);
219 NVDmaNext (pNv, (uint32_t)pNv->FB->offset);
221 NVDmaStart(pNv, NvImagePattern, PATTERN_FORMAT, 1);
222 NVDmaNext (pNv, patternFormat);
224 NVDmaStart(pNv, NvRectangle, RECT_FORMAT, 1);
225 NVDmaNext (pNv, rectFormat);
228 NVDmaStart(pNv, NvSolidLine, LINE_FORMAT, 1);
229 NVDmaNext (pNv, lineFormat);
232 pNv->currentRop = ~0; /* set to something invalid */
233 NVSetRopSolid(pScrn, GXcopy, ~0);
235 pNv->M2MFDirection = -1; /* invalid */
236 /*NVDmaKickoff(pNv);*/
239 Bool NVDmaCreateContextObject(NVPtr pNv, int handle, int class)
241 struct drm_nouveau_grobj_alloc cto;
244 cto.channel = pNv->fifo.channel;
247 ret = drmCommandWrite(pNv->drm_fd, DRM_NOUVEAU_GROBJ_ALLOC,
252 static void NVInitDmaCB(ScrnInfoPtr pScrn)
254 NVPtr pNv = NVPTR(pScrn);
255 unsigned int cb_location;
259 /* I'm not bothering to check for failures here, the DRM will fall back
260 * on defaults if anything's wrong (ie. out of AGP, invalid sizes)
263 if (pNv->GARTScratch)
264 cb_location = NOUVEAU_MEM_AGP | NOUVEAU_MEM_PCI_ACCEPTABLE;
267 cb_location = NOUVEAU_MEM_FB;
268 if((s = (char *)xf86GetOptValString(pNv->Options, OPTION_CMDBUF_LOCATION))) {
269 if(!xf86NameCmp(s, "AGP"))
270 cb_location = NOUVEAU_MEM_AGP;
271 else if (!xf86NameCmp(s, "VRAM"))
272 cb_location = NOUVEAU_MEM_FB;
273 else if (!xf86NameCmp(s, "PCI"))
274 cb_location = NOUVEAU_MEM_PCI;
276 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Invalid value \"%s\" for CBLocation\n", s);
278 NVDRMSetParam(pNv, NOUVEAU_SETPARAM_CMDBUF_LOCATION, cb_location);
280 /* CBSize == size of space reserved for *all* FIFOs in MiB */
281 if (xf86GetOptValInteger(pNv->Options, OPTION_CMDBUF_SIZE, &cb_size))
282 NVDRMSetParam(pNv, NOUVEAU_SETPARAM_CMDBUF_SIZE, (cb_size<<20));
285 Bool NVInitDma(ScrnInfoPtr pScrn)
287 NVPtr pNv = NVPTR(pScrn);
295 pNv->fifo.fb_ctxdma_handle = NvDmaFB;
296 pNv->fifo.tt_ctxdma_handle = NvDmaTT;
297 ret = drmCommandWriteRead(pNv->drm_fd, DRM_NOUVEAU_CHANNEL_ALLOC,
298 &pNv->fifo, sizeof(pNv->fifo));
300 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
301 "Could not allocate GPU channel: %d\n", ret);
305 ret = drmMap(pNv->drm_fd, pNv->fifo.cmdbuf, pNv->fifo.cmdbuf_size,
306 (drmAddressPtr)&pNv->dmaBase);
308 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
309 "Failed to map DMA push buffer: %d\n", ret);
313 ret = drmMap(pNv->drm_fd, pNv->fifo.ctrl, pNv->fifo.ctrl_size,
314 (drmAddressPtr)&pNv->FIFO);
316 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
317 "Failed to map FIFO control regs: %d\n", ret);
321 ret = drmMap(pNv->drm_fd, pNv->fifo.notifier, pNv->fifo.notifier_size,
322 (drmAddressPtr)&pNv->NotifierBlock);
324 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
325 "Failed to map notifier block: %d\n", ret);
329 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
330 "Using FIFO channel %d\n", pNv->fifo.channel);
331 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
332 " Control registers : %p (0x%08x)\n",
333 pNv->FIFO, pNv->fifo.ctrl);
334 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
335 " DMA command buffer: %p (0x%08x)\n",
336 pNv->dmaBase, pNv->fifo.cmdbuf);
337 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
338 " DMA cmdbuf length : %d KiB\n",
339 pNv->fifo.cmdbuf_size / 1024);
340 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
341 " DMA base PUT : 0x%08x\n", pNv->fifo.put_base);
343 pNv->dmaPut = pNv->dmaCurrent = READ_GET(pNv);
344 pNv->dmaMax = (pNv->fifo.cmdbuf_size >> 2) - 2;
345 pNv->dmaFree = pNv->dmaMax - pNv->dmaCurrent;
347 for (i=0; i<SKIPS; i++)
349 pNv->dmaFree -= SKIPS;