1/* 2Copyright (C) 2008 Francisco Jerez. All Rights Reserved. 3 4Permission is hereby granted, free of charge, to any person obtaining a copy of 5this software and associated documentation files (the "Software"), to deal in 6the Software without restriction, including without limitation the rights to 7use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 8of the Software, and to permit persons to whom the Software is furnished to do 9so, subject to the following conditions: 10 11The above copyright notice and this permission notice shall be included in all 12copies or substantial portions of the Software. 13 14THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FIT- 16NESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17XFREE86 PROJECT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 18AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 19WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20*/ 21 22#ifdef HAVE_CONFIG_H 23#include "config.h" 24#endif 25 26#include "smi.h" 27#include "smi_crtc.h" 28#include "smilynx.h" 29#include "smi_501.h" 30 31static void 32SMI_CrtcDPMS(xf86CrtcPtr crtc, 33 int mode) 34{ 35 ENTER(); 36 37 /* Nothing */ 38 39 LEAVE(); 40} 41 42static Bool 43SMI_CrtcLock (xf86CrtcPtr crtc) 44{ 45 ScrnInfoPtr pScrn = crtc->scrn; 46 SMIPtr pSmi = SMIPTR(pScrn); 47 48 ENTER(); 49 50 WaitIdle(); 51 52 LEAVE(FALSE); 53} 54 55static void 56SMI_CrtcUnlock (xf86CrtcPtr crtc) 57{ 58 ENTER(); 59 60 /* Nothing */ 61 62 LEAVE(); 63} 64 65static Bool 66SMI_CrtcModeFixup(xf86CrtcPtr crtc, 67 DisplayModePtr mode, 68 DisplayModePtr adjusted_mode) 69{ 70 ENTER(); 71 72 /* Nothing */ 73 74 LEAVE(TRUE); 75} 76 77static void 78SMI_CrtcPrepare(xf86CrtcPtr crtc) 79{ 80 ENTER(); 81 LEAVE(); 82} 83 84static void 85SMI_CrtcCommit(xf86CrtcPtr crtc) 86{ 87 ENTER(); 88 89 crtc->funcs->dpms(crtc,DPMSModeOn); 90 91 LEAVE(); 92} 93 94static void 95SMI_CrtcGammaSet(xf86CrtcPtr crtc, CARD16 *red, CARD16 *green, CARD16 *blue, 96 int size) 97{ 98 SMICrtcPrivatePtr crtcPriv = SMICRTC(crtc); 99 int i; 100 101 ENTER(); 102 103 for(i=0; i<256; i++){ 104 crtcPriv->lut_r[i] = red[i * size >> 8]; 105 crtcPriv->lut_g[i] = green[i * size >> 8]; 106 crtcPriv->lut_b[i] = blue[i * size >> 8]; 107 } 108 109 crtcPriv->load_lut(crtc); 110 111 LEAVE(); 112} 113 114static void * 115SMI_CrtcShadowAllocate (xf86CrtcPtr crtc, int width, int height) 116{ 117 ScrnInfoPtr pScrn = crtc->scrn; 118 SMIPtr pSmi = SMIPTR(pScrn); 119 SMICrtcPrivatePtr crtcPriv = SMICRTC(crtc); 120 int offset, size; 121 122 ENTER(); 123 124 size = ((width * pSmi->Bpp + 15) & ~15) * height; 125 offset = SMI_AllocateMemory(pScrn, &crtcPriv->shadowArea, size); 126 127 if (!crtcPriv->shadowArea) 128 LEAVE(NULL); 129 130 LEAVE(pSmi->FBBase + offset); 131} 132 133static PixmapPtr 134SMI_CrtcShadowCreate (xf86CrtcPtr crtc, void *data, int width, int height) 135{ 136 ScrnInfoPtr pScrn = crtc->scrn; 137 SMIPtr pSmi = SMIPTR(pScrn); 138 int aligned_pitch; 139 140 ENTER(); 141 142 aligned_pitch = (width * pSmi->Bpp + 15) & ~15; 143 144 LEAVE(GetScratchPixmapHeader(pScrn->pScreen,width,height,pScrn->depth, 145 pScrn->bitsPerPixel,aligned_pitch,data)); 146} 147 148static void 149SMI_CrtcShadowDestroy (xf86CrtcPtr crtc, PixmapPtr pPixmap, void *data) 150{ 151 ScrnInfoPtr pScrn = crtc->scrn; 152 SMIPtr pSmi = SMIPTR(pScrn); 153 SMICrtcPrivatePtr crtcPriv = SMICRTC(crtc); 154 155 ENTER(); 156 157 if (pSmi->useEXA && pPixmap) 158 FreeScratchPixmapHeader(pPixmap); 159 160 if (crtcPriv->shadowArea) { 161 SMI_FreeMemory(pScrn, crtcPriv->shadowArea); 162 crtcPriv->shadowArea = NULL; 163 } 164 165 LEAVE(); 166} 167 168static void 169SMI_CrtcDestroy (xf86CrtcPtr crtc) 170{ 171 ENTER(); 172 173 free(SMICRTC(crtc)); 174 free((xf86CrtcFuncsPtr)crtc->funcs); 175 176 LEAVE(); 177} 178 179static Bool 180SMI_CrtcConfigResize(ScrnInfoPtr pScrn, 181 int width, 182 int height) 183{ 184 SMIPtr pSmi = SMIPTR(pScrn); 185 xf86CrtcConfigPtr crtcConf = XF86_CRTC_CONFIG_PTR(pScrn); 186 int i; 187 xf86CrtcPtr crtc; 188 189 ENTER(); 190 191 /* Allocate another offscreen area and use it as screen, if it really has to be resized */ 192 if(!pSmi->NoAccel && pSmi->useEXA && 193 ( !pSmi->fbArea || width != pScrn->virtualX || height != pScrn->virtualY )){ 194 int aligned_pitch = (width*pSmi->Bpp + 15) & ~15; 195 196 ExaOffscreenArea* fbArea = exaOffscreenAlloc(pScrn->pScreen, aligned_pitch*height, 16, TRUE, NULL, NULL); 197 if(!fbArea){ 198 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 199 "SMI_CrtcConfigResize: Not enough memory to resize the framebuffer\n"); 200 LEAVE(FALSE); 201 } 202 203 if(pSmi->fbArea) 204 exaOffscreenFree(pScrn->pScreen, pSmi->fbArea); 205 206 pSmi->fbArea = fbArea; 207 pSmi->FBOffset = fbArea->offset; 208 pScrn->fbOffset = pSmi->FBOffset + pSmi->fbMapOffset; 209 210 pScrn->pScreen->ModifyPixmapHeader(pScrn->pScreen->GetScreenPixmap(pScrn->pScreen), 211 -1,-1,-1,-1,-1, pSmi->FBBase + pSmi->FBOffset); 212 213#if (XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(1, 9, 99, 1, 0)) 214 if(pScrn->pixmapPrivate.ptr) 215 /* The pixmap devPrivate just set may be overwritten by 216 xf86EnableDisableFBAccess */ 217 pScrn->pixmapPrivate.ptr = pSmi->FBBase + pSmi->FBOffset; 218#endif 219 220 /* Modify the screen pitch */ 221 pScrn->displayWidth = aligned_pitch / pSmi->Bpp; 222 pScrn->pScreen->ModifyPixmapHeader(pScrn->pScreen->GetScreenPixmap(pScrn->pScreen), 223 -1, -1, -1, -1, aligned_pitch, NULL); 224 225 /* Modify the screen dimensions */ 226 pScrn->virtualX = width; 227 pScrn->virtualY = height; 228 pScrn->pScreen->ModifyPixmapHeader(pScrn->pScreen->GetScreenPixmap(pScrn->pScreen), 229 width, height, -1, -1, 0, NULL); 230 } 231 232 /* Setup each crtc video processor */ 233 for(i=0;i<crtcConf->num_crtc;i++){ 234 crtc = crtcConf->crtc[i]; 235 SMICRTC(crtc)->video_init(crtc); 236 SMICRTC(crtc)->adjust_frame(crtc,crtc->x,crtc->y); 237 } 238 239 LEAVE(TRUE); 240} 241 242void 243SMI_CrtcFuncsInit_base(xf86CrtcFuncsPtr* crtcFuncs, SMICrtcPrivatePtr* crtcPriv){ 244 *crtcFuncs = xnfcalloc(sizeof(xf86CrtcFuncsRec), 1); 245 *crtcPriv = xnfcalloc(sizeof(SMICrtcPrivateRec), 1); 246 247 (*crtcFuncs)->dpms = SMI_CrtcDPMS; 248 (*crtcFuncs)->lock = SMI_CrtcLock; 249 (*crtcFuncs)->unlock = SMI_CrtcUnlock; 250 (*crtcFuncs)->mode_fixup = SMI_CrtcModeFixup; 251 (*crtcFuncs)->prepare = SMI_CrtcPrepare; 252 (*crtcFuncs)->commit = SMI_CrtcCommit; 253 (*crtcFuncs)->gamma_set = SMI_CrtcGammaSet; 254 (*crtcFuncs)->shadow_allocate = SMI_CrtcShadowAllocate; 255 (*crtcFuncs)->shadow_create = SMI_CrtcShadowCreate; 256 (*crtcFuncs)->shadow_destroy = SMI_CrtcShadowDestroy; 257 (*crtcFuncs)->destroy = SMI_CrtcDestroy; 258} 259 260static xf86CrtcConfigFuncsRec SMI_CrtcConfigFuncs = { 261 .resize = SMI_CrtcConfigResize 262}; 263 264Bool 265SMI_CrtcPreInit(ScrnInfoPtr pScrn) 266{ 267 SMIPtr pSmi = SMIPTR(pScrn); 268 269 ENTER(); 270 271 xf86CrtcConfigInit(pScrn,&SMI_CrtcConfigFuncs); 272 273 xf86CrtcSetSizeRange(pScrn,128,128,4096,4096); 274 275 if(SMI_MSOC_SERIES(pSmi->Chipset)){ 276 LEAVE( SMI501_CrtcPreInit(pScrn) ); 277 }else{ 278 LEAVE( SMILynx_CrtcPreInit(pScrn) ); 279 } 280} 281