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 /* There is a HW race condition with videoram command buffers.
20 * You can't jump to the location of your put offset. We write put
21 * at the jump offset + SKIPS dwords with noop padding in between
22 * to solve this problem
26 static void NVDumpLockupInfo(NVPtr pNv)
29 start=READ_GET(pNv)-20;
31 xf86DrvMsg(0, X_INFO, "Fifo dump (lockup 0x%04x,0x%04x):\n",READ_GET(pNv),pNv->dmaPut);
32 for(i=start;i<pNv->dmaPut+10;i++)
33 xf86DrvMsg(0, X_INFO, "[0x%04x] 0x%08x\n", i, pNv->dmaBase[i]);
34 xf86DrvMsg(0, X_INFO, "End of fifo dump\n");
38 NVLockedUp(ScrnInfoPtr pScrn)
40 NVPtr pNv = NVPTR(pScrn);
42 /* avoid re-entering FatalError on shutdown */
47 NVDumpLockupInfo(pNv);
49 FatalError("DMA queue hang: dmaPut=%x, current=%x, status=%x\n",
50 pNv->dmaPut, READ_GET(pNv), pNv->PGRAPH[NV_PGRAPH_STATUS/4]);
53 void NVDmaWait (ScrnInfoPtr pScrn, int size)
55 NVPtr pNv = NVPTR(pScrn);
61 t_start = GetTimeInMillis();
62 while(pNv->dmaFree < size) {
63 dmaGet = READ_GET(pNv);
65 if(pNv->dmaPut >= dmaGet) {
66 pNv->dmaFree = pNv->dmaMax - pNv->dmaCurrent;
67 if(pNv->dmaFree < size) {
68 NVDmaNext(pNv, (0x20000000|pNv->fifo.put_base));
70 if(pNv->dmaPut <= SKIPS) /* corner case - will be idle */
71 WRITE_PUT(pNv, SKIPS + 1);
73 if (GetTimeInMillis() - t_start > 2000)
75 dmaGet = READ_GET(pNv);
76 } while(dmaGet <= SKIPS);
78 WRITE_PUT(pNv, SKIPS);
79 pNv->dmaCurrent = pNv->dmaPut = SKIPS;
80 pNv->dmaFree = dmaGet - (SKIPS + 1);
83 pNv->dmaFree = dmaGet - pNv->dmaCurrent - 1;
86 if (GetTimeInMillis() - t_start > 2000)
91 void NVSync(ScrnInfoPtr pScrn)
93 NVPtr pNv = NVPTR(pScrn);
94 int t_start, timeout = 2000;
100 if(pNv->DMAKickoffCallback)
101 (*pNv->DMAKickoffCallback)(pNv);
103 /* Wait for entire FIFO to be processed */
104 t_start = GetTimeInMillis();
105 while((GetTimeInMillis() - t_start) < timeout &&
106 (READ_GET(pNv) != pNv->dmaPut));
107 if ((GetTimeInMillis() - t_start) >= timeout) {
112 /* Wait for channel to go completely idle */
113 subc = (pNv->Architecture >= NV_ARCH_50) ? NvSub2D : NvSubImageBlit;
114 NVNotifierReset(pScrn, pNv->Notifier0);
115 NVDmaStart(pNv, subc, 0x104, 1);
117 NVDmaStart(pNv, subc, 0x100, 1);
120 if (!NVNotifierWaitStatus(pScrn, pNv->Notifier0, 0, timeout))
124 void NVResetGraphics(ScrnInfoPtr pScrn)
126 NVPtr pNv = NVPTR(pScrn);
127 CARD32 surfaceFormat, patternFormat, rectFormat, lineFormat;
130 if(pNv->NoAccel) return;
132 pitch = pNv->CurrentLayout.displayWidth * (pNv->CurrentLayout.bitsPerPixel >> 3);
135 pNv->dmaPut = pNv->dmaCurrent = READ_GET(pNv);
136 pNv->dmaMax = (pNv->fifo.cmdbuf_size >> 2) - 2;
137 pNv->dmaFree = pNv->dmaMax - pNv->dmaCurrent;
139 /* assert there's enough room for the skips */
140 if(pNv->dmaFree <= SKIPS)
141 NVDmaWait(pScrn, SKIPS);
142 for (i=0; i<SKIPS; i++) {
146 pNv->dmaFree -= SKIPS;
149 NVAccelCommonInit(pScrn);
151 if (pNv->Architecture >= NV_ARCH_50)
155 NVDmaSetObjectOnSubchannel(pNv, NvSubContextSurfaces, NvContextSurfaces);
156 NVDmaSetObjectOnSubchannel(pNv, NvSubRectangle , NvRectangle );
157 NVDmaSetObjectOnSubchannel(pNv, NvSubScaledImage , NvScaledImage );
159 NVDmaSetObjectOnSubchannel(pNv, NvSubRop , NvRop );
160 NVDmaSetObjectOnSubchannel(pNv, NvSubImagePattern, NvImagePattern );
161 NVDmaSetObjectOnSubchannel(pNv, NvSubImageBlit , NvImageBlit );
163 if (pNv->GARTScratch)
164 NVDmaSetObjectOnSubchannel(pNv, NvSubMemFormat, NvMemFormat);
165 } else if (!pNv->useEXA) {
166 NVDmaSetObjectOnSubchannel(pNv, NvSubClipRectangle, NvClipRectangle);
167 NVDmaSetObjectOnSubchannel(pNv, NvSubSolidLine, NvSolidLine);
170 switch(pNv->CurrentLayout.depth) {
172 surfaceFormat = SURFACE_FORMAT_X8R8G8B8;
173 patternFormat = PATTERN_FORMAT_DEPTH24;
174 rectFormat = RECT_FORMAT_DEPTH24;
175 lineFormat = LINE_FORMAT_DEPTH24;
179 surfaceFormat = SURFACE_FORMAT_R5G6B5;
180 patternFormat = PATTERN_FORMAT_DEPTH16;
181 rectFormat = RECT_FORMAT_DEPTH16;
182 lineFormat = LINE_FORMAT_DEPTH16;
185 surfaceFormat = SURFACE_FORMAT_Y8;
186 patternFormat = PATTERN_FORMAT_DEPTH8;
187 rectFormat = RECT_FORMAT_DEPTH8;
188 lineFormat = LINE_FORMAT_DEPTH8;
192 NVDmaStart(pNv, NvSubContextSurfaces, SURFACE_FORMAT, 4);
193 NVDmaNext (pNv, surfaceFormat);
194 NVDmaNext (pNv, pitch | (pitch << 16));
195 NVDmaNext (pNv, (uint32_t)pNv->FB->offset);
196 NVDmaNext (pNv, (uint32_t)pNv->FB->offset);
198 NVDmaStart(pNv, NvSubImagePattern, PATTERN_FORMAT, 1);
199 NVDmaNext (pNv, patternFormat);
201 NVDmaStart(pNv, NvSubRectangle, RECT_FORMAT, 1);
202 NVDmaNext (pNv, rectFormat);
205 NVDmaStart(pNv, NvSubSolidLine, LINE_FORMAT, 1);
206 NVDmaNext (pNv, lineFormat);
209 pNv->currentRop = ~0; /* set to something invalid */
210 NVSetRopSolid(pScrn, GXcopy, ~0);
212 pNv->M2MFDirection = -1; /* invalid */
213 /*NVDmaKickoff(pNv);*/
216 Bool NVDmaCreateContextObject(NVPtr pNv, int handle, int class)
218 drm_nouveau_grobj_alloc_t cto;
221 cto.channel = pNv->fifo.channel;
224 ret = drmCommandWrite(pNv->drm_fd, DRM_NOUVEAU_GROBJ_ALLOC,
229 static void NVInitDmaCB(ScrnInfoPtr pScrn)
231 NVPtr pNv = NVPTR(pScrn);
232 unsigned int cb_location;
236 /* I'm not bothering to check for failures here, the DRM will fall back
237 * on defaults if anything's wrong (ie. out of AGP, invalid sizes)
240 if (pNv->GARTScratch)
241 cb_location = NOUVEAU_MEM_AGP | NOUVEAU_MEM_PCI_ACCEPTABLE;
244 cb_location = NOUVEAU_MEM_FB;
245 if((s = (char *)xf86GetOptValString(pNv->Options, OPTION_CMDBUF_LOCATION))) {
246 if(!xf86NameCmp(s, "AGP"))
247 cb_location = NOUVEAU_MEM_AGP;
248 else if (!xf86NameCmp(s, "VRAM"))
249 cb_location = NOUVEAU_MEM_FB;
250 else if (!xf86NameCmp(s, "PCI"))
251 cb_location = NOUVEAU_MEM_PCI;
253 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Invalid value \"%s\" for CBLocation\n", s);
255 NVDRMSetParam(pNv, NOUVEAU_SETPARAM_CMDBUF_LOCATION, cb_location);
257 /* CBSize == size of space reserved for *all* FIFOs in MiB */
258 if (xf86GetOptValInteger(pNv->Options, OPTION_CMDBUF_SIZE, &cb_size))
259 NVDRMSetParam(pNv, NOUVEAU_SETPARAM_CMDBUF_SIZE, (cb_size<<20));
262 Bool NVInitDma(ScrnInfoPtr pScrn)
264 NVPtr pNv = NVPTR(pScrn);
269 pNv->fifo.fb_ctxdma_handle = NvDmaFB;
270 pNv->fifo.tt_ctxdma_handle = NvDmaTT;
271 ret = drmCommandWriteRead(pNv->drm_fd, DRM_NOUVEAU_FIFO_ALLOC,
272 &pNv->fifo, sizeof(pNv->fifo));
274 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
275 "Could not allocate GPU channel: %d\n", ret);
279 ret = drmMap(pNv->drm_fd, pNv->fifo.cmdbuf, pNv->fifo.cmdbuf_size,
280 (drmAddressPtr)&pNv->dmaBase);
282 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
283 "Failed to map DMA push buffer: %d\n", ret);
287 ret = drmMap(pNv->drm_fd, pNv->fifo.ctrl, pNv->fifo.ctrl_size,
288 (drmAddressPtr)&pNv->FIFO);
290 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
291 "Failed to map FIFO control regs: %d\n", ret);
295 ret = drmMap(pNv->drm_fd, pNv->fifo.notifier, pNv->fifo.notifier_size,
296 (drmAddressPtr)&pNv->NotifierBlock);
298 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
299 "Failed to map notifier block: %d\n", ret);
303 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
304 "Using FIFO channel %d\n", pNv->fifo.channel);
305 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
306 " Control registers : %p (0x%08x)\n",
307 pNv->FIFO, pNv->fifo.ctrl);
308 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
309 " DMA command buffer: %p (0x%08x)\n",
310 pNv->dmaBase, pNv->fifo.cmdbuf);
311 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
312 " DMA cmdbuf length : %d KiB\n",
313 pNv->fifo.cmdbuf_size / 1024);
314 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
315 " DMA base PUT : 0x%08x\n", pNv->fifo.put_base);
317 pNv->dmaPut = pNv->dmaCurrent = 0;
318 pNv->dmaMax = (pNv->fifo.cmdbuf_size >> 2) - 2;
319 pNv->dmaFree = pNv->dmaMax - pNv->dmaCurrent;
321 for (i=0; i<SKIPS; i++)
323 pNv->dmaFree -= SKIPS;