1f29dbc25Smrg/* Copyright (c) 2008 Advanced Micro Devices, Inc. 2f29dbc25Smrg * 3f29dbc25Smrg * Permission is hereby granted, free of charge, to any person obtaining a copy 4f29dbc25Smrg * of this software and associated documentation files (the "Software"), to 5f29dbc25Smrg * deal in the Software without restriction, including without limitation the 6f29dbc25Smrg * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 7f29dbc25Smrg * sell copies of the Software, and to permit persons to whom the Software is 8f29dbc25Smrg * furnished to do so, subject to the following conditions: 9f29dbc25Smrg * 10f29dbc25Smrg * The above copyright notice and this permission notice shall be included in 11f29dbc25Smrg * all copies or substantial portions of the Software. 12f29dbc25Smrg * 13f29dbc25Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14f29dbc25Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15f29dbc25Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16f29dbc25Smrg * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17f29dbc25Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 18f29dbc25Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 19f29dbc25Smrg * IN THE SOFTWARE. 20f29dbc25Smrg * 21f29dbc25Smrg * Neither the name of the Advanced Micro Devices, Inc. nor the names of its 22f29dbc25Smrg * contributors may be used to endorse or promote products derived from this 23f29dbc25Smrg * software without specific prior written permission. 24f29dbc25Smrg */ 25f29dbc25Smrg 26f29dbc25Smrg#ifdef HAVE_CONFIG_H 27f29dbc25Smrg#include "config.h" 28f29dbc25Smrg#endif 29f29dbc25Smrg 3000be8644Schristos#include "xorg-server.h" 3100be8644Schristos 32f29dbc25Smrg#include "xf86.h" 33f29dbc25Smrg#include "geode.h" 34f29dbc25Smrg#include "xf86Crtc.h" 35f29dbc25Smrg#include "cim/cim_defs.h" 36f29dbc25Smrg#include "cim/cim_regs.h" 37f29dbc25Smrg 3804007ebaSmrgtypedef struct _LXOutputPrivateRec { 39f29dbc25Smrg int video_enable; 40f29dbc25Smrg unsigned long video_flags; 41f29dbc25Smrg GeodeMemPtr rotate_mem; 42f29dbc25Smrg} LXCrtcPrivateRec, *LXCrtcPrivatePtr; 43f29dbc25Smrg 44e9a8eab3Smrgvoid 45f29dbc25Smrglx_enable_dac_power(ScrnInfoPtr pScrni, int option) 46f29dbc25Smrg{ 47f29dbc25Smrg GeodeRec *pGeode = GEODEPTR(pScrni); 48f29dbc25Smrg 49f29dbc25Smrg df_set_crt_enable(DF_CRT_ENABLE); 50f29dbc25Smrg 51f29dbc25Smrg /* Turn off the DAC if we don't need the CRT */ 52f29dbc25Smrg 53f29dbc25Smrg if (option && (!(pGeode->Output & OUTPUT_CRT))) { 5404007ebaSmrg unsigned int misc = READ_VID32(DF_VID_MISC); 55f29dbc25Smrg 5604007ebaSmrg misc |= DF_DAC_POWER_DOWN; 5704007ebaSmrg WRITE_VID32(DF_VID_MISC, misc); 58f29dbc25Smrg } 59f29dbc25Smrg 60f29dbc25Smrg if (pGeode->Output & OUTPUT_PANEL) 6104007ebaSmrg df_set_panel_enable(1); 62f29dbc25Smrg} 63f29dbc25Smrg 64e9a8eab3Smrgvoid 65f29dbc25Smrglx_disable_dac_power(ScrnInfoPtr pScrni, int option) 66f29dbc25Smrg{ 67f29dbc25Smrg GeodeRec *pGeode = GEODEPTR(pScrni); 68f29dbc25Smrg 69f29dbc25Smrg if (pGeode->Output & OUTPUT_PANEL) 7004007ebaSmrg df_set_panel_enable(0); 71f29dbc25Smrg 72f29dbc25Smrg if (pGeode->Output & OUTPUT_CRT) { 73f29dbc25Smrg 7404007ebaSmrg /* Wait for the panel to finish its procedure */ 75f29dbc25Smrg 7604007ebaSmrg if (pGeode->Output & OUTPUT_PANEL) 7704007ebaSmrg while ((READ_VID32(DF_POWER_MANAGEMENT) & 2) == 0); 7804007ebaSmrg df_set_crt_enable(option); 79f29dbc25Smrg } 80f29dbc25Smrg} 81f29dbc25Smrg 82f29dbc25Smrgstatic void 83f29dbc25Smrglx_set_panel_mode(VG_DISPLAY_MODE * mode, DisplayModePtr pMode) 84f29dbc25Smrg{ 85f29dbc25Smrg int hsync, vsync; 86f29dbc25Smrg 87f29dbc25Smrg mode->mode_width = mode->panel_width = pMode->HDisplay; 88f29dbc25Smrg mode->mode_height = mode->panel_height = pMode->VDisplay; 89f29dbc25Smrg 90f29dbc25Smrg mode->hactive = pMode->HDisplay; 91f29dbc25Smrg mode->hblankstart = pMode->HDisplay; 92f29dbc25Smrg mode->hsyncstart = pMode->HSyncStart; 93f29dbc25Smrg mode->hsyncend = pMode->HSyncEnd; 94f29dbc25Smrg mode->hblankend = pMode->HTotal; 95f29dbc25Smrg mode->htotal = pMode->HTotal; 96f29dbc25Smrg 97f29dbc25Smrg mode->vactive = pMode->VDisplay; 98f29dbc25Smrg mode->vblankstart = pMode->VDisplay; 99f29dbc25Smrg mode->vsyncstart = pMode->VSyncStart; 100f29dbc25Smrg mode->vsyncend = pMode->VSyncEnd; 101f29dbc25Smrg mode->vblankend = pMode->VTotal; 102f29dbc25Smrg mode->vtotal = pMode->VTotal; 103f29dbc25Smrg 104f29dbc25Smrg mode->vactive_even = pMode->VDisplay; 105f29dbc25Smrg mode->vblankstart_even = pMode->VDisplay; 106f29dbc25Smrg mode->vsyncstart_even = pMode->VSyncStart; 107f29dbc25Smrg mode->vsyncend_even = pMode->VSyncEnd; 108f29dbc25Smrg mode->vblankend_even = pMode->VTotal; 109f29dbc25Smrg mode->vtotal_even = pMode->VTotal; 110f29dbc25Smrg 11104007ebaSmrg mode->frequency = (int) ((pMode->Clock / 1000.0) * 0x10000); 112f29dbc25Smrg 113f29dbc25Smrg /* In panel mode, Cimarron purposely swizzles these, 114f29dbc25Smrg * so we swizzle them first */ 115f29dbc25Smrg 116f29dbc25Smrg hsync = (pMode->Flags & V_NHSYNC) ? 0 : 1; 117f29dbc25Smrg vsync = (pMode->Flags & V_NVSYNC) ? 0 : 1; 118f29dbc25Smrg 119f29dbc25Smrg mode->flags |= (hsync) ? VG_MODEFLAG_NEG_HSYNC : 0; 120f29dbc25Smrg mode->flags |= (vsync) ? VG_MODEFLAG_NEG_VSYNC : 0; 121f29dbc25Smrg} 122f29dbc25Smrg 123f29dbc25Smrgstatic void 124f29dbc25Smrglx_set_crt_mode(VG_DISPLAY_MODE * mode, DisplayModePtr pMode) 125f29dbc25Smrg{ 126f29dbc25Smrg int hsync, vsync; 127f29dbc25Smrg 128f29dbc25Smrg mode->mode_width = mode->panel_width = pMode->HDisplay; 129f29dbc25Smrg mode->mode_height = mode->panel_height = pMode->VDisplay; 130f29dbc25Smrg 131f29dbc25Smrg mode->hactive = pMode->CrtcHDisplay; 132f29dbc25Smrg mode->hblankstart = pMode->CrtcHBlankStart; 133f29dbc25Smrg mode->hsyncstart = pMode->CrtcHSyncStart; 134f29dbc25Smrg mode->hsyncend = pMode->CrtcHSyncEnd; 135f29dbc25Smrg mode->hblankend = pMode->CrtcHBlankEnd; 136f29dbc25Smrg mode->htotal = pMode->CrtcHTotal; 137f29dbc25Smrg 138f29dbc25Smrg mode->vactive = pMode->CrtcVDisplay; 139f29dbc25Smrg mode->vblankstart = pMode->CrtcVBlankStart; 140f29dbc25Smrg mode->vsyncstart = pMode->CrtcVSyncStart; 141f29dbc25Smrg mode->vsyncend = pMode->CrtcVSyncEnd; 142f29dbc25Smrg mode->vblankend = pMode->CrtcVBlankEnd; 143f29dbc25Smrg mode->vtotal = pMode->CrtcVTotal; 144f29dbc25Smrg 145f29dbc25Smrg mode->vactive_even = pMode->CrtcVDisplay; 146f29dbc25Smrg mode->vblankstart_even = pMode->CrtcVBlankStart; 147f29dbc25Smrg mode->vsyncstart_even = pMode->CrtcVSyncStart; 148f29dbc25Smrg mode->vsyncend_even = pMode->CrtcVSyncEnd; 149f29dbc25Smrg mode->vblankend_even = pMode->CrtcVBlankEnd; 150f29dbc25Smrg mode->vtotal_even = pMode->CrtcVTotal; 151f29dbc25Smrg 15204007ebaSmrg mode->frequency = (int) ((pMode->Clock / 1000.0) * 0x10000); 153f29dbc25Smrg 154f29dbc25Smrg hsync = (pMode->Flags & V_NHSYNC) ? 1 : 0; 155f29dbc25Smrg vsync = (pMode->Flags & V_NVSYNC) ? 1 : 0; 156f29dbc25Smrg 157f29dbc25Smrg mode->flags |= (hsync) ? VG_MODEFLAG_NEG_HSYNC : 0; 158f29dbc25Smrg mode->flags |= (vsync) ? VG_MODEFLAG_NEG_VSYNC : 0; 159f29dbc25Smrg} 160f29dbc25Smrg 161f29dbc25Smrgstatic int 162f29dbc25Smrglx_set_mode(ScrnInfoPtr pScrni, DisplayModePtr pMode, int bpp) 163f29dbc25Smrg{ 164f29dbc25Smrg GeodeRec *pGeode = GEODEPTR(pScrni); 165f29dbc25Smrg VG_DISPLAY_MODE mode; 166f29dbc25Smrg int ret; 167f29dbc25Smrg 168f29dbc25Smrg memset(&mode, 0, sizeof(mode)); 169f29dbc25Smrg 170f29dbc25Smrg mode.flags |= pGeode->Output & OUTPUT_CRT ? VG_MODEFLAG_CRT_AND_FP : 0; 171f29dbc25Smrg 172f29dbc25Smrg if (pGeode->Output & OUTPUT_PANEL) { 17304007ebaSmrg mode.flags |= VG_MODEFLAG_PANELOUT; 17404007ebaSmrg if (pGeode->Output & OUTPUT_CRT) 17504007ebaSmrg mode.flags |= VG_MODEFLAG_CRT_AND_FP; 176f29dbc25Smrg } 177f29dbc25Smrg 178f29dbc25Smrg if (pGeode->Output & OUTPUT_PANEL && pGeode->Scale) 17904007ebaSmrg lx_set_panel_mode(&mode, pGeode->panelMode); 180f29dbc25Smrg else 18104007ebaSmrg lx_set_crt_mode(&mode, pMode); 182f29dbc25Smrg 183f29dbc25Smrg mode.src_width = pMode->HDisplay; 184f29dbc25Smrg mode.src_height = pMode->VDisplay; 185f29dbc25Smrg 186f29dbc25Smrg /* Set the filter coefficients to the default values */ 187f29dbc25Smrg vg_set_scaler_filter_coefficients(NULL, NULL); 188f29dbc25Smrg 189f29dbc25Smrg ret = vg_set_custom_mode(&mode, bpp); 190f29dbc25Smrg return (ret == CIM_STATUS_OK) ? 0 : -1; 191f29dbc25Smrg} 192f29dbc25Smrg 193f29dbc25Smrgstatic void 194f29dbc25Smrglx_crtc_dpms(xf86CrtcPtr crtc, int mode) 195f29dbc25Smrg{ 196f29dbc25Smrg ScrnInfoPtr pScrni = crtc->scrn; 197f29dbc25Smrg GeodeRec *pGeode = GEODEPTR(pScrni); 198f29dbc25Smrg 199f29dbc25Smrg if (pGeode->Output & OUTPUT_DCON) 20004007ebaSmrg DCONDPMSSet(pScrni, mode); 201f29dbc25Smrg 202f29dbc25Smrg switch (mode) { 203f29dbc25Smrg case DPMSModeOn: 20404007ebaSmrg lx_enable_dac_power(pScrni, 1); 20504007ebaSmrg break; 206f29dbc25Smrg 207f29dbc25Smrg case DPMSModeStandby: 20804007ebaSmrg lx_disable_dac_power(pScrni, DF_CRT_STANDBY); 20904007ebaSmrg break; 210f29dbc25Smrg 211f29dbc25Smrg case DPMSModeSuspend: 21204007ebaSmrg lx_disable_dac_power(pScrni, DF_CRT_SUSPEND); 21304007ebaSmrg break; 214f29dbc25Smrg 215f29dbc25Smrg case DPMSModeOff: 21604007ebaSmrg lx_disable_dac_power(pScrni, DF_CRT_DISABLE); 21704007ebaSmrg break; 218f29dbc25Smrg } 219f29dbc25Smrg} 220f29dbc25Smrg 221f29dbc25Smrgstatic Bool 222f29dbc25Smrglx_crtc_lock(xf86CrtcPtr crtc) 223f29dbc25Smrg{ 224f29dbc25Smrg /* Wait until the GPU is idle */ 225f29dbc25Smrg gp_wait_until_idle(); 226f29dbc25Smrg return TRUE; 227f29dbc25Smrg} 228f29dbc25Smrg 229f29dbc25Smrgstatic void 230f29dbc25Smrglx_crtc_unlock(xf86CrtcPtr crtc) 231f29dbc25Smrg{ 232f29dbc25Smrg /* Nothing to do here */ 233f29dbc25Smrg} 234f29dbc25Smrg 235f29dbc25Smrgstatic void 236f29dbc25Smrglx_crtc_prepare(xf86CrtcPtr crtc) 237f29dbc25Smrg{ 238f29dbc25Smrg LXCrtcPrivatePtr lx_crtc = crtc->driver_private; 239f29dbc25Smrg 240f29dbc25Smrg /* Disable the video */ 241f29dbc25Smrg df_get_video_enable(&lx_crtc->video_enable, &lx_crtc->video_flags); 242f29dbc25Smrg 243f29dbc25Smrg if (lx_crtc->video_enable) 24404007ebaSmrg df_set_video_enable(0, 0); 245f29dbc25Smrg 246f29dbc25Smrg /* Turn off compression */ 247f29dbc25Smrg vg_set_compression_enable(0); 248f29dbc25Smrg 249f29dbc25Smrg /* Hide the cursor */ 250f29dbc25Smrg crtc->funcs->hide_cursor(crtc); 251f29dbc25Smrg 252f29dbc25Smrg /* Turn off the display */ 253f29dbc25Smrg crtc->funcs->dpms(crtc, DPMSModeOff); 254f29dbc25Smrg} 255f29dbc25Smrg 256f29dbc25Smrgstatic Bool 257f29dbc25Smrglx_crtc_mode_fixup(xf86CrtcPtr crtc, DisplayModePtr mode, 25804007ebaSmrg DisplayModePtr adjusted_mode) 259f29dbc25Smrg{ 260f29dbc25Smrg return TRUE; 261f29dbc25Smrg} 262f29dbc25Smrg 263f29dbc25Smrgstatic void 264f29dbc25Smrglx_crtc_mode_set(xf86CrtcPtr crtc, DisplayModePtr mode, 26504007ebaSmrg DisplayModePtr adjusted_mode, int x, int y) 266f29dbc25Smrg{ 267f29dbc25Smrg ScrnInfoPtr pScrni = crtc->scrn; 268f29dbc25Smrg GeodeRec *pGeode = GEODEPTR(pScrni); 269f29dbc25Smrg DF_VIDEO_SOURCE_PARAMS vs_odd, vs_even; 270170d5fdcSmrg unsigned int rpitch; 271f29dbc25Smrg 272f29dbc25Smrg df_get_video_source_configuration(&vs_odd, &vs_even); 273f29dbc25Smrg 274f29dbc25Smrg /* Note - the memory gets adjusted when virtualX/virtualY 275f29dbc25Smrg * gets changed - so we don't need to worry about it here 276f29dbc25Smrg */ 277f29dbc25Smrg 278f29dbc25Smrg if (lx_set_mode(pScrni, adjusted_mode, pScrni->bitsPerPixel)) 27904007ebaSmrg ErrorF("ERROR! Unable to set the mode!\n"); 280f29dbc25Smrg 281f29dbc25Smrg /* The output gets turned in in the output code as 282f29dbc25Smrg * per convention */ 283f29dbc25Smrg 284170d5fdcSmrg /* For rotation, any write to the frame buffer region marks 285170d5fdcSmrg * the retire frame as dirty. 286170d5fdcSmrg */ 287170d5fdcSmrg if (crtc->rotatedData != NULL) { 28804007ebaSmrg rpitch = pScrni->displayWidth * (pScrni->bitsPerPixel / 8); 28904007ebaSmrg vg_set_display_pitch(rpitch); 290170d5fdcSmrg } 291170d5fdcSmrg else 29204007ebaSmrg vg_set_display_pitch(pGeode->Pitch); 293f29dbc25Smrg gp_set_bpp(pScrni->bitsPerPixel); 294f29dbc25Smrg 295f29dbc25Smrg /* Set the acceleration offset if we are drawing to a shadow */ 296f29dbc25Smrg if (crtc->rotatedData != NULL) 29704007ebaSmrg vg_set_display_offset((unsigned int) ((char *) crtc->rotatedData - 29804007ebaSmrg (char *) pGeode->FBBase)); 299f29dbc25Smrg else 30004007ebaSmrg vg_set_display_offset(0); 301f29dbc25Smrg 302c744f008Smrg /* FIXME: What's up with X and Y? Does that come into play 303f29dbc25Smrg * here? */ 304f29dbc25Smrg 305f29dbc25Smrg df_configure_video_source(&vs_odd, &vs_even); 306f29dbc25Smrg 307f29dbc25Smrg vg_wait_vertical_blank(); 308f29dbc25Smrg} 309f29dbc25Smrg 310f29dbc25Smrgstatic void 311f29dbc25Smrglx_crtc_commit(xf86CrtcPtr crtc) 312f29dbc25Smrg{ 313f29dbc25Smrg LXCrtcPrivatePtr lx_crtc = crtc->driver_private; 314f29dbc25Smrg ScrnInfoPtr pScrni = crtc->scrn; 315f29dbc25Smrg GeodeRec *pGeode = GEODEPTR(pScrni); 316f29dbc25Smrg 317f29dbc25Smrg /* Turn back on the sreen */ 318f29dbc25Smrg crtc->funcs->dpms(crtc, DPMSModeOn); 319f29dbc25Smrg 320f29dbc25Smrg /* Turn on compression */ 321f29dbc25Smrg 322f29dbc25Smrg if (pGeode->Compression) { 32304007ebaSmrg vg_configure_compression(&(pGeode->CBData)); 32404007ebaSmrg vg_set_compression_enable(1); 325f29dbc25Smrg } 326f29dbc25Smrg 327f29dbc25Smrg /* Load the cursor */ 328f29dbc25Smrg if (crtc->scrn->pScreen != NULL) { 329861b9feeSmrg#ifdef HAVE_XF86_CURSOR_RESET_CURSOR 330861b9feeSmrg xf86CursorResetCursor(crtc->scrn->pScreen); 331861b9feeSmrg#else 33204007ebaSmrg xf86_reload_cursors(crtc->scrn->pScreen); 333861b9feeSmrg#endif 33404007ebaSmrg crtc->funcs->hide_cursor(crtc); 33504007ebaSmrg crtc->cursor_shown = FALSE; 336f29dbc25Smrg } 337f29dbc25Smrg 338f29dbc25Smrg /* Renable the video */ 339f29dbc25Smrg 340f29dbc25Smrg if (lx_crtc->video_enable) 34104007ebaSmrg df_set_video_enable(lx_crtc->video_enable, lx_crtc->video_flags); 342f29dbc25Smrg 343f29dbc25Smrg lx_crtc->video_enable = 0; 344f29dbc25Smrg lx_crtc->video_flags = 0; 345f29dbc25Smrg} 346f29dbc25Smrg 347f29dbc25Smrgstatic void 34804007ebaSmrglx_crtc_gamma_set(xf86CrtcPtr crtc, CARD16 *red, CARD16 *green, 34904007ebaSmrg CARD16 *blue, int size) 350f29dbc25Smrg{ 351f29dbc25Smrg unsigned int dcfg; 352f29dbc25Smrg int i; 353f29dbc25Smrg 354f29dbc25Smrg assert(size == 256); 355f29dbc25Smrg 356170d5fdcSmrg /* We need the Gamma Correction for video - fading operation, 357170d5fdcSmrg * the values address should be plused for every cycle. 358170d5fdcSmrg * Special for Screensaver Operation. 359170d5fdcSmrg */ 360170d5fdcSmrg 361f29dbc25Smrg for (i = 0; i < 256; i++) { 36204007ebaSmrg unsigned int val; 36304007ebaSmrg 364170d5fdcSmrg (*red) &= 0xff00; 365170d5fdcSmrg (*green) &= 0xff00; 366170d5fdcSmrg (*blue) &= 0xff00; 36704007ebaSmrg val = (*(red++) << 8) | *(green++) | (*(blue++) >> 8); 368f29dbc25Smrg 36904007ebaSmrg df_set_video_palette_entry(i, val); 370f29dbc25Smrg } 371f29dbc25Smrg 372f29dbc25Smrg /* df_set_video_palette_entry automatically turns on 373f29dbc25Smrg * gamma for video - if this gets called, we assume that 374f29dbc25Smrg * RandR wants it set for graphics, so reverse cimarron 375f29dbc25Smrg */ 376f29dbc25Smrg 377f29dbc25Smrg dcfg = READ_VID32(DF_DISPLAY_CONFIG); 378f29dbc25Smrg dcfg &= ~DF_DCFG_GV_PAL_BYP; 379f29dbc25Smrg WRITE_VID32(DF_DISPLAY_CONFIG, dcfg); 380f29dbc25Smrg} 381f29dbc25Smrg 382170d5fdcSmrg /* The Xserver has a scratch pixmap allocation routine that will 383170d5fdcSmrg * try to use the existing scratch pixmap if possible. When the driver 384170d5fdcSmrg * or any other user stop using it, it need to clear out any pixmap 385170d5fdcSmrg * state (private data etc) otherwise the next user may get stale data. 386170d5fdcSmrg */ 387170d5fdcSmrg 388170d5fdcSmrg /* Use our own wrapper to allocate a pixmap for wrapping a buffer object 389170d5fdcSmrg * It removes using scratch pixmaps for rotate. 390170d5fdcSmrg */ 391170d5fdcSmrgstatic PixmapPtr 392170d5fdcSmrglx_create_bo_pixmap(ScreenPtr pScreen, 39304007ebaSmrg int width, int height, 39404007ebaSmrg int depth, int bpp, int pitch, pointer pPixData) 395170d5fdcSmrg{ 396170d5fdcSmrg PixmapPtr pixmap; 397170d5fdcSmrg 3987aef237fSmrg#if XORG_VERSION_CURRENT >= XORG_VERSION_NUMERIC(1,5,0,0,0) 39904007ebaSmrg pixmap = (*pScreen->CreatePixmap) (pScreen, 0, 0, depth, 0); 4007aef237fSmrg#else 40104007ebaSmrg pixmap = (*pScreen->CreatePixmap) (pScreen, 0, 0, depth); 4027aef237fSmrg#endif 4037aef237fSmrg 404170d5fdcSmrg if (!pixmap) 40504007ebaSmrg return NULL; 40604007ebaSmrg if (!(*pScreen->ModifyPixmapHeader) (pixmap, width, height, 40704007ebaSmrg depth, bpp, pitch, pPixData)) { 40804007ebaSmrg /* ModifyPixmapHeader failed, so we can't use it as scratch pixmap 40904007ebaSmrg */ 41004007ebaSmrg (*pScreen->DestroyPixmap) (pixmap); 41104007ebaSmrg return NULL; 412170d5fdcSmrg } 413170d5fdcSmrg 414170d5fdcSmrg return pixmap; 415170d5fdcSmrg} 416170d5fdcSmrg 417170d5fdcSmrgstatic void 418170d5fdcSmrglx_destory_bo_pixmap(PixmapPtr pixmap) 419170d5fdcSmrg{ 420170d5fdcSmrg ScreenPtr pScreen = pixmap->drawable.pScreen; 421170d5fdcSmrg 42204007ebaSmrg (*pScreen->DestroyPixmap) (pixmap); 423170d5fdcSmrg} 424170d5fdcSmrg 425170d5fdcSmrg /* Allocates shadow memory, and allocating a new space for Rotation. 426170d5fdcSmrg * The size is measured in bytes, and the offset from the beginning 427170d5fdcSmrg * of card space is returned. 428170d5fdcSmrg */ 429170d5fdcSmrg 430170d5fdcSmrgstatic Bool 431170d5fdcSmrgLXAllocShadow(ScrnInfoPtr pScrni, int size) 432170d5fdcSmrg{ 433170d5fdcSmrg GeodeRec *pGeode = GEODEPTR(pScrni); 434170d5fdcSmrg 435170d5fdcSmrg if (pGeode->shadowArea) { 43604007ebaSmrg if (pGeode->shadowArea->size != size) { 43704007ebaSmrg exaOffscreenFree(pScrni->pScreen, pGeode->shadowArea); 43804007ebaSmrg pGeode->shadowArea = NULL; 43904007ebaSmrg } 440170d5fdcSmrg } 441170d5fdcSmrg 442170d5fdcSmrg if (pGeode->shadowArea == NULL) { 44304007ebaSmrg pGeode->shadowArea = 44404007ebaSmrg exaOffscreenAlloc(pScrni->pScreen, size, 4, TRUE, NULL, NULL); 445170d5fdcSmrg 44604007ebaSmrg if (pGeode->shadowArea == NULL) 44704007ebaSmrg return FALSE; 448170d5fdcSmrg } 449170d5fdcSmrg 450170d5fdcSmrg pScrni->fbOffset = pGeode->shadowArea->offset; 451170d5fdcSmrg return TRUE; 452170d5fdcSmrg} 453170d5fdcSmrg 454f29dbc25Smrgstatic void * 455f29dbc25Smrglx_crtc_shadow_allocate(xf86CrtcPtr crtc, int width, int height) 456f29dbc25Smrg{ 457f29dbc25Smrg ScrnInfoPtr pScrni = crtc->scrn; 458f29dbc25Smrg GeodePtr pGeode = GEODEPTR(pScrni); 459f29dbc25Smrg unsigned int rpitch, size; 460f29dbc25Smrg 461f29dbc25Smrg rpitch = pScrni->displayWidth * (pScrni->bitsPerPixel / 8); 462f29dbc25Smrg size = rpitch * height; 463f29dbc25Smrg 464170d5fdcSmrg /* Allocate shadow memory */ 465170d5fdcSmrg if (LXAllocShadow(pScrni, size) == FALSE) { 46604007ebaSmrg xf86DrvMsg(pScrni->scrnIndex, X_ERROR, 46704007ebaSmrg "Couldn't allocate the shadow memory for rotation\n"); 46804007ebaSmrg xf86DrvMsg(pScrni->scrnIndex, X_ERROR, 46904007ebaSmrg " You need 0x%x bytes, but only 0x%x bytes are available\n", 47004007ebaSmrg size, GeodeOffscreenFreeSize(pGeode)); 471f29dbc25Smrg 47204007ebaSmrg return NULL; 473f29dbc25Smrg } 474f29dbc25Smrg 475170d5fdcSmrg memset(pGeode->FBBase + pGeode->shadowArea->offset, 0, size); 476170d5fdcSmrg return pGeode->FBBase + pGeode->shadowArea->offset; 477f29dbc25Smrg} 478f29dbc25Smrg 479f29dbc25Smrgstatic PixmapPtr 480f29dbc25Smrglx_crtc_shadow_create(xf86CrtcPtr crtc, void *data, int width, int height) 481f29dbc25Smrg{ 482f29dbc25Smrg ScrnInfoPtr pScrni = crtc->scrn; 483f29dbc25Smrg PixmapPtr rpixmap; 484170d5fdcSmrg unsigned int rpitch; 485f29dbc25Smrg 486170d5fdcSmrg rpitch = pScrni->displayWidth * (pScrni->bitsPerPixel / 8); 487f29dbc25Smrg if (!data) 48804007ebaSmrg data = lx_crtc_shadow_allocate(crtc, width, height); 489f29dbc25Smrg 490170d5fdcSmrg rpixmap = lx_create_bo_pixmap(pScrni->pScreen, 49104007ebaSmrg width, height, pScrni->depth, 49204007ebaSmrg pScrni->bitsPerPixel, rpitch, data); 493f29dbc25Smrg 494f29dbc25Smrg if (rpixmap == NULL) { 49504007ebaSmrg xf86DrvMsg(pScrni->scrnIndex, X_ERROR, 49604007ebaSmrg "Couldn't allocate shadow pixmap for rotated CRTC\n"); 497f29dbc25Smrg } 498f29dbc25Smrg 499f29dbc25Smrg return rpixmap; 500f29dbc25Smrg} 501f29dbc25Smrg 502f29dbc25Smrgstatic void 503f29dbc25Smrglx_crtc_shadow_destroy(xf86CrtcPtr crtc, PixmapPtr rpixmap, void *data) 504f29dbc25Smrg{ 505f29dbc25Smrg ScrnInfoPtr pScrni = crtc->scrn; 506f29dbc25Smrg GeodeRec *pGeode = GEODEPTR(pScrni); 507f29dbc25Smrg 508f29dbc25Smrg if (rpixmap) 50904007ebaSmrg lx_destory_bo_pixmap(rpixmap); 510f29dbc25Smrg 511170d5fdcSmrg /* Free shadow memory */ 512f29dbc25Smrg if (data) { 51304007ebaSmrg gp_wait_until_idle(); 51404007ebaSmrg if (pGeode->shadowArea != NULL) { 51504007ebaSmrg exaOffscreenFree(pScrni->pScreen, pGeode->shadowArea); 51604007ebaSmrg pGeode->shadowArea = NULL; 51704007ebaSmrg } 518f29dbc25Smrg } 519f29dbc25Smrg} 520f29dbc25Smrg 521f29dbc25Smrgstatic void 522f29dbc25Smrglx_crtc_set_cursor_colors(xf86CrtcPtr crtc, int bg, int fg) 523f29dbc25Smrg{ 524f29dbc25Smrg vg_set_mono_cursor_colors(bg, fg); 525f29dbc25Smrg} 526f29dbc25Smrg 527f29dbc25Smrgstatic void 528f29dbc25Smrglx_crtc_set_cursor_position(xf86CrtcPtr crtc, int x, int y) 529f29dbc25Smrg{ 530f29dbc25Smrg VG_PANNING_COORDINATES panning; 53104007ebaSmrg 532f29dbc25Smrg vg_set_cursor_position(x, y, &panning); 533f29dbc25Smrg} 534f29dbc25Smrg 535f29dbc25Smrgstatic void 536f29dbc25Smrglx_crtc_show_cursor(xf86CrtcPtr crtc) 537f29dbc25Smrg{ 538f29dbc25Smrg vg_set_cursor_enable(1); 539f29dbc25Smrg} 540f29dbc25Smrg 541f29dbc25Smrgstatic void 542f29dbc25Smrglx_crtc_hide_cursor(xf86CrtcPtr crtc) 543f29dbc25Smrg{ 544f29dbc25Smrg vg_set_cursor_enable(0); 545f29dbc25Smrg} 546f29dbc25Smrg 547f29dbc25Smrgstatic void 548f29dbc25Smrglx_crtc_load_cursor_argb(xf86CrtcPtr crtc, CARD32 *image) 549f29dbc25Smrg{ 550f29dbc25Smrg LXLoadARGBCursorImage(crtc->scrn, (unsigned char *) image); 551f29dbc25Smrg} 552f29dbc25Smrg 553f29dbc25Smrgstatic const xf86CrtcFuncsRec lx_crtc_funcs = { 554f29dbc25Smrg .dpms = lx_crtc_dpms, 555f29dbc25Smrg .lock = lx_crtc_lock, 556f29dbc25Smrg .unlock = lx_crtc_unlock, 557f29dbc25Smrg .mode_fixup = lx_crtc_mode_fixup, 558f29dbc25Smrg .prepare = lx_crtc_prepare, 559f29dbc25Smrg .mode_set = lx_crtc_mode_set, 560f29dbc25Smrg .commit = lx_crtc_commit, 561f29dbc25Smrg .gamma_set = lx_crtc_gamma_set, 562f29dbc25Smrg .shadow_create = lx_crtc_shadow_create, 563f29dbc25Smrg .shadow_allocate = lx_crtc_shadow_allocate, 564f29dbc25Smrg .shadow_destroy = lx_crtc_shadow_destroy, 565f29dbc25Smrg .set_cursor_colors = lx_crtc_set_cursor_colors, 566f29dbc25Smrg .set_cursor_position = lx_crtc_set_cursor_position, 567f29dbc25Smrg .show_cursor = lx_crtc_show_cursor, 568f29dbc25Smrg .hide_cursor = lx_crtc_hide_cursor, 569f29dbc25Smrg .load_cursor_argb = lx_crtc_load_cursor_argb, 570f29dbc25Smrg}; 571f29dbc25Smrg 572f29dbc25Smrgvoid 573f29dbc25SmrgLXSetupCrtc(ScrnInfoPtr pScrni) 574f29dbc25Smrg{ 575f29dbc25Smrg xf86CrtcPtr crtc; 576f29dbc25Smrg LXCrtcPrivatePtr lxpriv; 577f29dbc25Smrg 578f29dbc25Smrg crtc = xf86CrtcCreate(pScrni, &lx_crtc_funcs); 579f29dbc25Smrg 580f29dbc25Smrg if (crtc == NULL) { 58104007ebaSmrg ErrorF("ERROR - failed to create a CRTC\n"); 58204007ebaSmrg return; 583f29dbc25Smrg } 584f29dbc25Smrg 58504007ebaSmrg lxpriv = xnfcalloc(1, sizeof(LXCrtcPrivateRec)); 586f29dbc25Smrg 587f29dbc25Smrg if (!lxpriv) { 58804007ebaSmrg xf86CrtcDestroy(crtc); 58904007ebaSmrg ErrorF("unable to allocate memory for lxpriv\n"); 59004007ebaSmrg return; 591f29dbc25Smrg } 592f29dbc25Smrg 593f29dbc25Smrg crtc->driver_private = lxpriv; 594f29dbc25Smrg} 595