Ps3GpuTransferData cannot handle negative X and Y copy directions, fallback to softwa...
[ps3freebsd_xf86_video_ps3gpu.git] / src / ps3gpu_driver.c
blob21624746d53ea992894303da1882e69c486e4f3a
1 /*-
2 * Copyright (C) 2011 glevand <geoffrey.levand@mail.ru>
3 * All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer,
10 * without modification, immediately at the beginning of the file.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 * $FreeBSD$
29 #ifdef HAVE_CONFIG_H
30 #include "config.h"
31 #endif
33 #include "xf86.h"
34 #include "xf86_OSproc.h"
36 #include "xf86Cursor.h"
38 #include "exa.h"
40 #include <sys/types.h>
41 #include <sys/stat.h>
42 #include <sys/uio.h>
43 #include <sys/ioctl.h>
44 #include <sys/mman.h>
45 #include <fcntl.h>
46 #include <unistd.h>
48 #include "ps3gpu_ctl.h"
50 #include "ps3gpu.h"
51 #include "ps3gpu_cursor.h"
52 #include "ps3gpu_accel.h"
54 #define PS3GPU_VERSION 4000
55 #define PS3GPU_NAME "ps3gpu"
56 #define PS3GPU_DRIVER_NAME "ps3gpu"
57 #define PS3GPU_MAJOR_VERSION 0
58 #define PS3GPU_MINOR_VERSION 1
59 #define PS3GPU_PATCHLEVEL 0
61 #define PS3GPU_DEVICE_PATH "/dev/ps3gpu"
63 #ifdef XFree86LOADER
65 static pointer Ps3GpuSetup(pointer module, pointer opts,
66 int *errmaj, int *errmin);
67 static const OptionInfoRec *Ps3GpuAvailableOptions(int chipid, int busid);
68 static void Ps3GpuIdentify(int flags);
69 static Bool Ps3GpuProbe(DriverPtr drv, int flags);
70 static Bool Ps3GpuPreInit(ScrnInfoPtr pScrn, int flags);
71 static Bool Ps3GpuScreenInit(int scrnIndex, ScreenPtr pScreen,
72 int argc, char **argv);
73 static Bool Ps3GpuCloseScreen(int scrnIndex, ScreenPtr pScreen);
74 static void Ps3GpuFreeScreen(int scrnIndex, int flags);
75 static Bool Ps3GpuSaveScreen(ScreenPtr pScreen, int mode);
76 static ModeStatus Ps3GpuValidMode(int scrnIndex, DisplayModePtr mode,
77 Bool verbose, int flags);
78 static Bool Ps3GpuSwitchMode(int scrnIndex, DisplayModePtr mode, int flags);
79 static Bool Ps3GpuSetMode(ScrnInfoPtr pScrn, DisplayModePtr mode);
80 static void Ps3GpuAdjustFrame(int scrnIndex, int x, int y, int flags);
81 static Bool Ps3GpuEnterVT(int scrnIndex, int flags);
82 static void Ps3GpuLeaveVT(int scrnIndex, int flags);
83 static void Ps3GpuSave(ScrnInfoPtr pScrn);
84 static void Ps3GpuRestore(ScrnInfoPtr pScrn);
85 static Bool Ps3GpuMapMem(ScrnInfoPtr pScrn);
86 static Bool Ps3GpuUnmapMem(ScrnInfoPtr pScrn);
87 static Bool Ps3GpuDriverFunc(ScrnInfoPtr pScrn, xorgDriverFuncOp op,
88 pointer ptr);
90 #endif /* XFree86LOADER */
92 _X_EXPORT DriverRec PS3GPU = {
93 PS3GPU_VERSION,
94 PS3GPU_DRIVER_NAME,
95 Ps3GpuIdentify,
96 Ps3GpuProbe,
97 Ps3GpuAvailableOptions,
98 NULL,
100 Ps3GpuDriverFunc
103 static SymTabRec Ps3GpuChipsets[] = {
104 { 0, "ps3gpu" },
105 { -1, NULL }
108 enum {
109 OPTION_SHADOW_FB,
110 OPTION_SW_CURSOR,
111 OPTION_NOACCEL
114 static const OptionInfoRec Ps3GpuOptions[] = {
115 { OPTION_SHADOW_FB, "ShadowFB", OPTV_BOOLEAN, { 0 }, FALSE },
116 { OPTION_SW_CURSOR, "SWcursor", OPTV_BOOLEAN, { 0 }, FALSE },
117 { OPTION_NOACCEL, "NoAccel", OPTV_BOOLEAN, { 0 }, FALSE },
118 { -1, NULL, OPTV_NONE, { 0 }, FALSE }
121 #ifdef XFree86LOADER
123 static XF86ModuleVersionInfo Ps3GpuVersRec = {
124 "ps3gpu",
125 MODULEVENDORSTRING,
126 MODINFOSTRING1,
127 MODINFOSTRING2,
128 XORG_VERSION_CURRENT,
129 PS3GPU_MAJOR_VERSION,
130 PS3GPU_MINOR_VERSION,
131 PS3GPU_PATCHLEVEL,
132 ABI_CLASS_VIDEODRV,
133 ABI_VIDEODRV_VERSION,
134 NULL,
135 { 0, 0, 0, 0 }
138 _X_EXPORT XF86ModuleData ps3gpuModuleData = { &Ps3GpuVersRec, Ps3GpuSetup, NULL };
140 static pointer
141 Ps3GpuSetup(pointer module, pointer opts,
142 int *errmaj, int *errmin)
144 static Bool setupDone = FALSE;
146 if (!setupDone) {
147 setupDone = TRUE;
148 xf86AddDriver(&PS3GPU, module, HaveDriverFuncs);
149 return ((pointer) 1);
150 } else {
151 if (errmaj != NULL)
152 *errmaj = LDR_ONCEONLY;
153 return (NULL);
157 #endif /* XFree86LOADER */
159 static Bool
160 Ps3GpuGetRec(ScrnInfoPtr pScrn)
162 if (pScrn->driverPrivate)
163 return (TRUE);
165 pScrn->driverPrivate = xnfcalloc(sizeof(Ps3GpuRec), 1);
167 return (TRUE);
170 static void
171 Ps3GpuFreeRec(ScrnInfoPtr pScrn)
173 if (!pScrn->driverPrivate)
174 return;
176 xfree(pScrn->driverPrivate);
178 pScrn->driverPrivate = NULL;
181 static const OptionInfoRec *
182 Ps3GpuAvailableOptions(int chipid, int busid)
184 return (Ps3GpuOptions);
187 static void
188 Ps3GpuIdentify(int flags)
190 xf86PrintChipsets(PS3GPU_NAME, "driver for PS3 GPU", Ps3GpuChipsets);
193 static Bool
194 Ps3GpuProbe(DriverPtr drv, int flags)
196 ScrnInfoPtr pScrn = NULL;
197 GDevPtr *devSections;
198 int numDevSections;
199 Bool foundScreen = FALSE;
200 int i;
202 if (flags & PROBE_DETECT)
203 return (FALSE);
205 numDevSections = xf86MatchDevice(PS3GPU_DRIVER_NAME, &devSections);
206 if (numDevSections <= 0)
207 return (FALSE);
209 if (numDevSections > 1) {
210 xf86Msg(X_ERROR, "Ignoring additional device sections\n");
211 numDevSections = 1;
214 for (i = 0; i < numDevSections; i++) {
215 int entityIndex = xf86ClaimFbSlot(drv, 0, devSections[i],
216 TRUE);
218 pScrn = xf86ConfigFbEntity(NULL, 0, entityIndex,
219 NULL, NULL, NULL, NULL);
220 if (pScrn) {
221 pScrn->driverVersion = PS3GPU_VERSION;
222 pScrn->driverName = PS3GPU_DRIVER_NAME;
223 pScrn->name = PS3GPU_NAME;
224 pScrn->Probe = Ps3GpuProbe;
225 pScrn->PreInit = Ps3GpuPreInit;
226 pScrn->ScreenInit = Ps3GpuScreenInit;
227 pScrn->FreeScreen = Ps3GpuFreeScreen;
228 pScrn->SwitchMode = Ps3GpuSwitchMode;
229 pScrn->AdjustFrame = Ps3GpuAdjustFrame;
230 pScrn->EnterVT = Ps3GpuEnterVT;
231 pScrn->LeaveVT = Ps3GpuLeaveVT;
232 pScrn->ValidMode = Ps3GpuValidMode;
234 foundScreen = TRUE;
238 xfree(devSections);
240 return (foundScreen);
243 static Bool
244 Ps3GpuPreInit(ScrnInfoPtr pScrn, int flags)
246 Ps3GpuPtr gPtr;
247 GDevPtr device = xf86GetEntityInfo(pScrn->entityList[0])->device;
248 rgb rgbZeros = { 0, 0, 0 };
249 rgb rgbMasks = { 0x00ff0000, 0x0000ff00, 0x000000ff };
250 Gamma gammaZeroes = { 0.0, 0.0, 0.0 };
251 DisplayModePtr mode;
252 int i;
254 if (flags & PROBE_DETECT)
255 return (FALSE);
257 pScrn->monitor = pScrn->confScreen->monitor;
259 if (!Ps3GpuGetRec(pScrn))
260 return (FALSE);
262 gPtr = PS3GPUPTR(pScrn);
264 pScrn->monitor = pScrn->confScreen->monitor;
266 if (pScrn->numEntities > 1)
267 return (FALSE);
269 gPtr->pEnt = xf86GetEntityInfo(pScrn->entityList[0]);
271 pScrn->chipset = (char *) xf86TokenToString(Ps3GpuChipsets,
272 gPtr->pEnt->chipset);
274 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Chipset is a %s\n",
275 pScrn->chipset);
277 if (!xf86SetDepthBpp(pScrn, 0, 0, 0, Support32bppFb)) {
278 return (FALSE);
279 } else {
280 switch (pScrn->depth) {
281 case 24:
282 break;
283 default:
284 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
285 "Given depth (%d) is not supported by this driver\n",
286 pScrn->depth);
287 return (FALSE);
291 xf86PrintDepthBpp(pScrn);
293 if (pScrn->depth == 8)
294 pScrn->rgbBits = 8;
296 if (!xf86SetWeight(pScrn, rgbZeros, rgbMasks))
297 return (FALSE);
299 if (!xf86SetDefaultVisual(pScrn, -1))
300 return (FALSE);
302 if (!xf86SetGamma(pScrn, gammaZeroes))
303 return (FALSE);
305 xf86CollectOptions(pScrn, device->options);
307 if (!(gPtr->options = xalloc(sizeof(Ps3GpuOptions))))
308 return (FALSE);
310 memcpy(gPtr->options, Ps3GpuOptions, sizeof(Ps3GpuOptions));
312 xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, gPtr->options);
314 if (device->videoRam != 0) {
315 pScrn->videoRam = device->videoRam;
316 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "VideoRAM: %d kByte\n",
317 pScrn->videoRam);
318 } else {
319 pScrn->videoRam = 64 * 1024;
320 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "VideoRAM: %d kByte\n",
321 pScrn->videoRam);
324 xf86GetOptValBool(gPtr->options, OPTION_SHADOW_FB, &gPtr->shadowFB);
325 xf86GetOptValBool(gPtr->options, OPTION_SW_CURSOR, &gPtr->swCursor);
326 xf86GetOptValBool(gPtr->options, OPTION_NOACCEL, &gPtr->noAccel);
328 if (gPtr->shadowFB) {
329 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
330 "Using Shadow Framebuffer\n");
333 if (gPtr->swCursor) {
334 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
335 "Using Software Cursor\n");
338 if (!gPtr->noAccel) {
339 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
340 "Acceleration disabled\n");
343 pScrn->progClock = TRUE;
345 mode = (DisplayModePtr) xalloc(sizeof(DisplayModeRec));
346 mode->prev = mode;
347 mode->next = mode;
348 mode->name = "ps3gpu current mode";
349 mode->status = MODE_OK;
350 mode->type = M_T_BUILTIN;
351 mode->Clock = 0;
352 mode->HDisplay = 1920;
353 mode->HSyncStart = 0;
354 mode->HSyncEnd = 0;
355 mode->HTotal = 0;
356 mode->HSkew = 0;
357 mode->VDisplay = 1080;
358 mode->VSyncStart = 0;
359 mode->VSyncEnd = 0;
360 mode->VTotal = 0;
361 mode->VScan = 0;
362 mode->Flags = 0;
364 if (pScrn->modes != NULL) {
365 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
366 "Ignoring mode specification from screen section\n");
369 pScrn->currentMode = pScrn->modes = mode;
371 pScrn->virtualX = mode->HDisplay;
372 pScrn->virtualY = mode->VDisplay;
373 pScrn->displayWidth = pScrn->virtualX;
375 xf86PrintModes(pScrn);
377 xf86SetDpi(pScrn, 0, 0);
379 if (gPtr->shadowFB) {
380 if (!xf86LoadSubModule(pScrn, "shadow")) {
381 Ps3GpuFreeRec(pScrn);
382 return (FALSE);
386 if (!xf86LoadSubModule(pScrn, "fb")) {
387 Ps3GpuFreeRec(pScrn);
388 return (FALSE);
391 if (!gPtr->noAccel) {
392 if (!xf86LoadSubModule(pScrn, "exa")) {
393 Ps3GpuFreeRec(pScrn);
394 return (FALSE);
398 return (TRUE);
401 static Bool
402 Ps3GpuScreenInit(int scrnIndex, ScreenPtr pScreen,
403 int argc, char **argv)
405 ScrnInfoPtr pScrn;
406 Ps3GpuPtr gPtr;
407 int err;
409 pScrn = xf86Screens[pScreen->myNum];
410 gPtr = PS3GPUPTR(pScrn);
412 if (!Ps3GpuMapMem(pScrn))
413 return (FALSE);
415 if (!Ps3GpuSetMode(pScrn, pScrn->currentMode))
416 return (FALSE);
418 Ps3GpuAdjustFrame(scrnIndex, pScrn->frameX0, pScrn->frameY0, 0);
420 miClearVisualTypes();
422 err = miSetVisualTypes(pScrn->depth,
423 miGetDefaultVisualMask(pScrn->depth),
424 pScrn->rgbBits, pScrn->defaultVisual);
425 if (!err)
426 return (FALSE);
428 if (!miSetPixmapDepths())
429 return (FALSE);
431 err = fbScreenInit(pScreen, gPtr->fbBase, pScrn->virtualX,
432 pScrn->virtualY, pScrn->xDpi, pScrn->yDpi, pScrn->displayWidth,
433 pScrn->bitsPerPixel);
434 if (!err)
435 return (FALSE);
437 if (pScrn->depth > 8) {
438 VisualPtr visual = pScreen->visuals + pScreen->numVisuals;
440 while (--visual >= pScreen->visuals) {
441 if ((visual->class | DynamicClass) == DirectColor) {
442 visual->offsetRed = pScrn->offset.red;
443 visual->offsetGreen = pScrn->offset.green;
444 visual->offsetBlue = pScrn->offset.blue;
445 visual->redMask = pScrn->mask.red;
446 visual->greenMask = pScrn->mask.green;
447 visual->blueMask = pScrn->mask.blue;
452 fbPictureInit(pScreen, 0, 0);
454 xf86SetBlackWhitePixels(pScreen);
456 miInitializeBackingStore(pScreen);
457 xf86SetBackingStore(pScreen);
458 xf86SetSilkenMouse(pScreen);
460 miDCInitialize(pScreen, xf86GetPointerScreenFuncs());
462 if (!gPtr->swCursor)
463 Ps3GpuCursorInit(pScreen);
465 if (!gPtr->noAccel)
466 Ps3GpuAccelInit(pScreen);
468 if(!miCreateDefColormap(pScreen))
469 return (FALSE);
471 pScreen->SaveScreen = Ps3GpuSaveScreen;
473 gPtr->closeScreen = pScreen->CloseScreen;
474 pScreen->CloseScreen = Ps3GpuCloseScreen;
476 if (serverGeneration == 1)
477 xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options);
479 return (TRUE);
482 static Bool
483 Ps3GpuCloseScreen(int scrnIndex, ScreenPtr pScreen)
485 ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
486 Ps3GpuPtr gPtr = PS3GPUPTR(pScrn);
488 if (pScrn->vtSema) {
489 Ps3GpuRestore(pScrn);
490 Ps3GpuUnmapMem(pScrn);
493 if (gPtr->cursorInfo)
494 xf86DestroyCursorInfoRec(gPtr->cursorInfo);
496 pScrn->vtSema = FALSE;
498 pScreen->CloseScreen = gPtr->closeScreen;
500 return (*pScreen->CloseScreen)(scrnIndex, pScreen);
503 static void
504 Ps3GpuFreeScreen(int scrnIndex, int flags)
506 Ps3GpuFreeRec(xf86Screens[scrnIndex]);
509 static Bool
510 Ps3GpuSaveScreen(ScreenPtr pScreen, int mode)
512 return (TRUE);
515 static ModeStatus
516 Ps3GpuValidMode(int scrnIndex, DisplayModePtr mode,
517 Bool verbose, int flags)
519 return (MODE_OK);
522 static Bool
523 Ps3GpuSwitchMode(int scrnIndex, DisplayModePtr mode, int flags)
525 return (TRUE);
528 static Bool
529 Ps3GpuSetMode(ScrnInfoPtr pScrn, DisplayModePtr mode)
531 Ps3GpuPtr gPtr = PS3GPUPTR(pScrn);
532 struct ps3gpu_ctl_flip flip;
533 int err;
535 pScrn->vtSema = TRUE;
537 flip.context_id = gPtr->gpuContextId;
538 flip.head = PS3GPU_CTL_HEAD_A;
539 flip.offset = gPtr->fbHandle;
541 err = ioctl(gPtr->fd, PS3GPU_CTL_FLIP, &flip);
542 if (err) {
543 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
544 "Failed to flip head A\n");
545 return (FALSE);
548 flip.context_id = gPtr->gpuContextId;
549 flip.head = PS3GPU_CTL_HEAD_B;
550 flip.offset = gPtr->fbHandle;
552 err = ioctl(gPtr->fd, PS3GPU_CTL_FLIP, &flip);
553 if (err) {
554 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
555 "Failed to flip head B\n");
556 return (FALSE);
559 return (TRUE);
562 static void
563 Ps3GpuAdjustFrame(int scrnIndex, int x, int y, int flags)
567 static Bool
568 Ps3GpuEnterVT(int scrnIndex, int flags)
570 ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
572 if (!Ps3GpuSetMode(pScrn, pScrn->currentMode))
573 return (FALSE);
575 return (TRUE);
578 static void
579 Ps3GpuLeaveVT(int scrnIndex, int flags)
583 static void
584 Ps3GpuSave(ScrnInfoPtr pScrn)
588 static void
589 Ps3GpuRestore(ScrnInfoPtr pScrn)
593 static Bool
594 Ps3GpuMapMem(ScrnInfoPtr pScrn)
596 Ps3GpuPtr gPtr = PS3GPUPTR(pScrn);
597 struct ps3gpu_ctl_context_allocate contextAllocate;
598 struct ps3gpu_ctl_memory_allocate memoryAllocate;
599 int err;
601 gPtr->fd = open(PS3GPU_DEVICE_PATH, O_RDWR | O_NONBLOCK);
602 if (gPtr->fd < 0) {
603 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
604 "Failed to open GPU device\n");
605 return (FALSE);
608 gPtr->fbSize = (pScrn->videoRam - 1024) * 1024;
610 contextAllocate.vram_size = pScrn->videoRam / 1024;
612 err = ioctl(gPtr->fd, PS3GPU_CTL_CONTEXT_ALLOCATE,
613 &contextAllocate);
614 if (err) {
615 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
616 "Failed to allocate GPU context\n");
617 return (FALSE);
620 gPtr->gpuContextId = contextAllocate.context_id;
621 gPtr->gpuControlHandle = contextAllocate.control_handle;
622 gPtr->gpuControlSize = contextAllocate.control_size;
624 memoryAllocate.context_id = contextAllocate.context_id;
625 memoryAllocate.type = PS3GPU_CTL_MEMORY_TYPE_VIDEO;
626 memoryAllocate.size = gPtr->fbSize;
627 memoryAllocate.align = 12;
629 err = ioctl(gPtr->fd, PS3GPU_CTL_MEMORY_ALLOCATE,
630 &memoryAllocate);
631 if (err) {
632 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
633 "Failed to allocate framebuffer memory\n");
634 return (FALSE);
637 gPtr->fbHandle = memoryAllocate.handle;
638 gPtr->fbGpuAddress = memoryAllocate.gpu_addr;
640 gPtr->fbBase = (pointer) mmap(NULL, gPtr->fbSize,
641 PROT_READ | PROT_WRITE, MAP_SHARED, gPtr->fd,
642 gPtr->fbHandle);
643 if (gPtr->fbBase == (pointer *) MAP_FAILED) {
644 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
645 "Failed to map framebuffer memory\n");
646 return (FALSE);
649 return (TRUE);
652 static Bool
653 Ps3GpuUnmapMem(ScrnInfoPtr pScrn)
655 Ps3GpuPtr gPtr = PS3GPUPTR(pScrn);
657 close(gPtr->fd);
659 gPtr->fbBase = NULL;
661 return (TRUE);
664 static Bool
665 Ps3GpuDriverFunc(ScrnInfoPtr pScrn, xorgDriverFuncOp op,
666 pointer ptr)
668 CARD32 *flag;
670 switch (op) {
671 case GET_REQUIRED_HW_INTERFACES:
672 flag = (CARD32 *) ptr;
673 *flag = 0;
674 return (TRUE);
675 default:
676 return (FALSE);