| /** |
| * \file server/radeon_dri.c |
| * \brief File to perform the device-specific initialization tasks typically |
| * done in the X server. |
| * |
| * Here they are converted to run in the client (or perhaps a standalone |
| * process), and to work with the frame buffer device rather than the X |
| * server infrastructure. |
| */ |
| |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <string.h> |
| #include <errno.h> |
| #include <unistd.h> |
| |
| #include "driver.h" |
| #include "drm.h" |
| #include "memops.h" |
| |
| #include "radeon.h" |
| #include "radeon_dri.h" |
| #include "radeon_macros.h" |
| #include "radeon_reg.h" |
| #include "drm_sarea.h" |
| |
| static size_t radeon_drm_page_size; |
| |
| static int RadeonSetParam(const DRIDriverContext *ctx, int param, int value) |
| { |
| drm_radeon_setparam_t sp; |
| |
| memset(&sp, 0, sizeof(sp)); |
| sp.param = param; |
| sp.value = value; |
| |
| if (drmCommandWrite(ctx->drmFD, DRM_RADEON_SETPARAM, &sp, sizeof(sp))) { |
| return -1; |
| } |
| |
| return 0; |
| } |
| |
| /** |
| * \brief Wait for free FIFO entries. |
| * |
| * \param ctx display handle. |
| * \param entries number of free entries to wait. |
| * |
| * It polls the free entries from the chip until it reaches the requested value |
| * or a timeout (3000 tries) occurs. Aborts the program if the FIFO times out. |
| */ |
| static void RADEONWaitForFifo( const DRIDriverContext *ctx, |
| int entries ) |
| { |
| unsigned char *RADEONMMIO = ctx->MMIOAddress; |
| int i; |
| |
| for (i = 0; i < 3000; i++) { |
| int fifo_slots = |
| INREG(RADEON_RBBM_STATUS) & RADEON_RBBM_FIFOCNT_MASK; |
| if (fifo_slots >= entries) return; |
| } |
| |
| /* There are recoveries possible, but I haven't seen them work |
| * in practice: |
| */ |
| fprintf(stderr, "FIFO timed out: %d entries, stat=0x%08x\n", |
| INREG(RADEON_RBBM_STATUS) & RADEON_RBBM_FIFOCNT_MASK, |
| INREG(RADEON_RBBM_STATUS)); |
| exit(1); |
| } |
| |
| /** |
| * \brief Read a PLL register. |
| * |
| * \param ctx display handle. |
| * \param addr PLL register index. |
| * |
| * \return value of the PLL register. |
| */ |
| static unsigned int RADEONINPLL( const DRIDriverContext *ctx, int addr) |
| { |
| unsigned char *RADEONMMIO = ctx->MMIOAddress; |
| unsigned int data; |
| |
| OUTREG8(RADEON_CLOCK_CNTL_INDEX, addr & 0x3f); |
| data = INREG(RADEON_CLOCK_CNTL_DATA); |
| |
| return data; |
| } |
| |
| /** |
| * \brief Reset graphics card to known state. |
| * |
| * \param ctx display handle. |
| * |
| * Resets the values of several Radeon registers. |
| */ |
| static void RADEONEngineReset( const DRIDriverContext *ctx ) |
| { |
| unsigned char *RADEONMMIO = ctx->MMIOAddress; |
| unsigned int clock_cntl_index; |
| unsigned int mclk_cntl; |
| unsigned int rbbm_soft_reset; |
| unsigned int host_path_cntl; |
| int i; |
| |
| OUTREGP(RADEON_RB2D_DSTCACHE_CTLSTAT, |
| RADEON_RB2D_DC_FLUSH_ALL, |
| ~RADEON_RB2D_DC_FLUSH_ALL); |
| for (i = 0; i < 512; i++) { |
| if (!(INREG(RADEON_RB2D_DSTCACHE_CTLSTAT) & RADEON_RB2D_DC_BUSY)) |
| break; |
| } |
| |
| clock_cntl_index = INREG(RADEON_CLOCK_CNTL_INDEX); |
| |
| mclk_cntl = INPLL(ctx, RADEON_MCLK_CNTL); |
| OUTPLL(RADEON_MCLK_CNTL, (mclk_cntl | |
| RADEON_FORCEON_MCLKA | |
| RADEON_FORCEON_MCLKB | |
| RADEON_FORCEON_YCLKA | |
| RADEON_FORCEON_YCLKB | |
| RADEON_FORCEON_MC | |
| RADEON_FORCEON_AIC)); |
| |
| /* Soft resetting HDP thru RBBM_SOFT_RESET register can cause some |
| * unexpected behaviour on some machines. Here we use |
| * RADEON_HOST_PATH_CNTL to reset it. |
| */ |
| host_path_cntl = INREG(RADEON_HOST_PATH_CNTL); |
| rbbm_soft_reset = INREG(RADEON_RBBM_SOFT_RESET); |
| |
| OUTREG(RADEON_RBBM_SOFT_RESET, (rbbm_soft_reset | |
| RADEON_SOFT_RESET_CP | |
| RADEON_SOFT_RESET_HI | |
| RADEON_SOFT_RESET_SE | |
| RADEON_SOFT_RESET_RE | |
| RADEON_SOFT_RESET_PP | |
| RADEON_SOFT_RESET_E2 | |
| RADEON_SOFT_RESET_RB)); |
| INREG(RADEON_RBBM_SOFT_RESET); |
| OUTREG(RADEON_RBBM_SOFT_RESET, (rbbm_soft_reset & |
| (unsigned int) ~(RADEON_SOFT_RESET_CP | |
| RADEON_SOFT_RESET_HI | |
| RADEON_SOFT_RESET_SE | |
| RADEON_SOFT_RESET_RE | |
| RADEON_SOFT_RESET_PP | |
| RADEON_SOFT_RESET_E2 | |
| RADEON_SOFT_RESET_RB))); |
| INREG(RADEON_RBBM_SOFT_RESET); |
| |
| OUTREG(RADEON_HOST_PATH_CNTL, host_path_cntl | RADEON_HDP_SOFT_RESET); |
| INREG(RADEON_HOST_PATH_CNTL); |
| OUTREG(RADEON_HOST_PATH_CNTL, host_path_cntl); |
| |
| OUTREG(RADEON_RBBM_SOFT_RESET, rbbm_soft_reset); |
| |
| OUTREG(RADEON_CLOCK_CNTL_INDEX, clock_cntl_index); |
| OUTPLL(RADEON_MCLK_CNTL, mclk_cntl); |
| } |
| |
| /** |
| * \brief Restore the drawing engine. |
| * |
| * \param ctx display handle |
| * |
| * Resets the graphics card and sets initial values for several registers of |
| * the card's drawing engine. |
| * |
| * Turns on the radeon command processor engine (i.e., the ringbuffer). |
| */ |
| static int RADEONEngineRestore( const DRIDriverContext *ctx ) |
| { |
| RADEONInfoPtr info = ctx->driverPrivate; |
| unsigned char *RADEONMMIO = ctx->MMIOAddress; |
| int pitch64, datatype, dp_gui_master_cntl, err; |
| |
| fprintf(stderr, "%s\n", __FUNCTION__); |
| |
| OUTREG(RADEON_RB3D_CNTL, 0); |
| RADEONEngineReset( ctx ); |
| |
| switch (ctx->bpp) { |
| case 16: datatype = 4; break; |
| case 32: datatype = 6; break; |
| default: return 0; |
| } |
| |
| dp_gui_master_cntl = |
| ((datatype << RADEON_GMC_DST_DATATYPE_SHIFT) |
| | RADEON_GMC_CLR_CMP_CNTL_DIS); |
| |
| pitch64 = ((ctx->shared.virtualWidth * (ctx->bpp / 8) + 0x3f)) >> 6; |
| |
| RADEONWaitForFifo(ctx, 1); |
| OUTREG(RADEON_DEFAULT_OFFSET, ((INREG(RADEON_DEFAULT_OFFSET) & 0xC0000000) |
| | (pitch64 << 22))); |
| |
| RADEONWaitForFifo(ctx, 1); |
| OUTREG(RADEON_SURFACE_CNTL, RADEON_SURF_TRANSLATION_DIS); |
| |
| RADEONWaitForFifo(ctx, 1); |
| OUTREG(RADEON_DEFAULT_SC_BOTTOM_RIGHT, (RADEON_DEFAULT_SC_RIGHT_MAX |
| | RADEON_DEFAULT_SC_BOTTOM_MAX)); |
| |
| RADEONWaitForFifo(ctx, 1); |
| OUTREG(RADEON_DP_GUI_MASTER_CNTL, (dp_gui_master_cntl |
| | RADEON_GMC_BRUSH_SOLID_COLOR |
| | RADEON_GMC_SRC_DATATYPE_COLOR)); |
| |
| RADEONWaitForFifo(ctx, 7); |
| OUTREG(RADEON_DST_LINE_START, 0); |
| OUTREG(RADEON_DST_LINE_END, 0); |
| OUTREG(RADEON_DP_BRUSH_FRGD_CLR, 0xffffffff); |
| OUTREG(RADEON_DP_BRUSH_BKGD_CLR, 0); |
| OUTREG(RADEON_DP_SRC_FRGD_CLR, 0xffffffff); |
| OUTREG(RADEON_DP_SRC_BKGD_CLR, 0); |
| OUTREG(RADEON_DP_WRITE_MASK, 0xffffffff); |
| OUTREG(RADEON_AUX_SC_CNTL, 0); |
| |
| /* RADEONWaitForIdleMMIO(ctx); */ |
| usleep(100); |
| |
| |
| OUTREG(RADEON_GEN_INT_CNTL, info->gen_int_cntl); |
| if (info->colorTiling) |
| info->crtc_offset_cntl |= RADEON_CRTC_TILE_EN; |
| OUTREG(RADEON_CRTC_OFFSET_CNTL, info->crtc_offset_cntl); |
| |
| /* Initialize and start the CP if required */ |
| if ((err = drmCommandNone(ctx->drmFD, DRM_RADEON_CP_START)) != 0) { |
| fprintf(stderr, "%s: CP start %d\n", __FUNCTION__, err); |
| return 0; |
| } |
| |
| return 1; |
| } |
| |
| |
| /** |
| * \brief Shutdown the drawing engine. |
| * |
| * \param ctx display handle |
| * |
| * Turns off the command processor engine & restores the graphics card |
| * to a state that fbdev understands. |
| */ |
| static int RADEONEngineShutdown( const DRIDriverContext *ctx ) |
| { |
| drm_radeon_cp_stop_t stop; |
| int ret, i; |
| |
| stop.flush = 1; |
| stop.idle = 1; |
| |
| ret = drmCommandWrite(ctx->drmFD, DRM_RADEON_CP_STOP, &stop, |
| sizeof(drm_radeon_cp_stop_t)); |
| |
| if (ret == 0) { |
| return 0; |
| } else if (errno != EBUSY) { |
| return -errno; |
| } |
| |
| stop.flush = 0; |
| |
| i = 0; |
| do { |
| ret = drmCommandWrite(ctx->drmFD, DRM_RADEON_CP_STOP, &stop, |
| sizeof(drm_radeon_cp_stop_t)); |
| } while (ret && errno == EBUSY && i++ < 10); |
| |
| if (ret == 0) { |
| return 0; |
| } else if (errno != EBUSY) { |
| return -errno; |
| } |
| |
| stop.idle = 0; |
| |
| if (drmCommandWrite(ctx->drmFD, DRM_RADEON_CP_STOP, |
| &stop, sizeof(drm_radeon_cp_stop_t))) { |
| return -errno; |
| } else { |
| return 0; |
| } |
| } |
| |
| /** |
| * \brief Compute base 2 logarithm. |
| * |
| * \param val value. |
| * |
| * \return base 2 logarithm of \p val. |
| */ |
| static int RADEONMinBits(int val) |
| { |
| int bits; |
| |
| if (!val) return 1; |
| for (bits = 0; val; val >>= 1, ++bits); |
| return bits; |
| } |
| |
| /** |
| * \brief Initialize the AGP state |
| * |
| * \param ctx display handle. |
| * \param info driver private data. |
| * |
| * \return one on success, or zero on failure. |
| * |
| * Acquires and enables the AGP device. Reserves memory in the AGP space for |
| * the ring buffer, vertex buffers and textures. Initialize the Radeon |
| * registers to point to that memory and add client mappings. |
| */ |
| static int RADEONDRIAgpInit( const DRIDriverContext *ctx, RADEONInfoPtr info) |
| { |
| unsigned char *RADEONMMIO = ctx->MMIOAddress; |
| unsigned long mode; |
| int ret; |
| int s, l; |
| |
| if (drmAgpAcquire(ctx->drmFD) < 0) { |
| fprintf(stderr, "[gart] AGP not available\n"); |
| return 0; |
| } |
| |
| /* Modify the mode if the default mode is not appropriate for this |
| * particular combination of graphics card and AGP chipset. |
| */ |
| mode = drmAgpGetMode(ctx->drmFD); /* Default mode */ |
| |
| /* Disable fast write entirely - too many lockups. |
| */ |
| mode &= ~RADEON_AGP_MODE_MASK; |
| switch (ctx->agpmode) { |
| case 4: mode |= RADEON_AGP_4X_MODE; |
| case 2: mode |= RADEON_AGP_2X_MODE; |
| case 1: default: mode |= RADEON_AGP_1X_MODE; |
| } |
| |
| if (drmAgpEnable(ctx->drmFD, mode) < 0) { |
| fprintf(stderr, "[gart] AGP not enabled\n"); |
| drmAgpRelease(ctx->drmFD); |
| return 0; |
| } |
| else |
| fprintf(stderr, "[gart] AGP enabled at %dx\n", ctx->agpmode); |
| |
| /* Workaround for some hardware bugs */ |
| if (info->ChipFamily < CHIP_FAMILY_R200) |
| OUTREG(RADEON_AGP_CNTL, INREG(RADEON_AGP_CNTL) | 0x000e0000); |
| |
| info->gartOffset = 0; |
| |
| if ((ret = drmAgpAlloc(ctx->drmFD, info->gartSize*1024*1024, 0, NULL, |
| &info->gartMemHandle)) < 0) { |
| fprintf(stderr, "[gart] Out of memory (%d)\n", ret); |
| drmAgpRelease(ctx->drmFD); |
| return 0; |
| } |
| fprintf(stderr, |
| "[gart] %d kB allocated with handle 0x%08x\n", |
| info->gartSize*1024, (unsigned)info->gartMemHandle); |
| |
| if (drmAgpBind(ctx->drmFD, |
| info->gartMemHandle, info->gartOffset) < 0) { |
| fprintf(stderr, "[gart] Could not bind\n"); |
| drmAgpFree(ctx->drmFD, info->gartMemHandle); |
| drmAgpRelease(ctx->drmFD); |
| return 0; |
| } |
| |
| /* Initialize the CP ring buffer data */ |
| info->ringStart = info->gartOffset; |
| info->ringMapSize = info->ringSize*1024*1024 + radeon_drm_page_size; |
| |
| info->ringReadOffset = info->ringStart + info->ringMapSize; |
| info->ringReadMapSize = radeon_drm_page_size; |
| |
| /* Reserve space for vertex/indirect buffers */ |
| info->bufStart = info->ringReadOffset + info->ringReadMapSize; |
| info->bufMapSize = info->bufSize*1024*1024; |
| |
| /* Reserve the rest for AGP textures */ |
| info->gartTexStart = info->bufStart + info->bufMapSize; |
| s = (info->gartSize*1024*1024 - info->gartTexStart); |
| l = RADEONMinBits((s-1) / RADEON_NR_TEX_REGIONS); |
| if (l < RADEON_LOG_TEX_GRANULARITY) l = RADEON_LOG_TEX_GRANULARITY; |
| info->gartTexMapSize = (s >> l) << l; |
| info->log2GARTTexGran = l; |
| |
| if (drmAddMap(ctx->drmFD, info->ringStart, info->ringMapSize, |
| DRM_AGP, DRM_READ_ONLY, &info->ringHandle) < 0) { |
| fprintf(stderr, "[gart] Could not add ring mapping\n"); |
| return 0; |
| } |
| fprintf(stderr, "[gart] ring handle = 0x%08x\n", info->ringHandle); |
| |
| |
| if (drmAddMap(ctx->drmFD, info->ringReadOffset, info->ringReadMapSize, |
| DRM_AGP, DRM_READ_ONLY, &info->ringReadPtrHandle) < 0) { |
| fprintf(stderr, |
| "[gart] Could not add ring read ptr mapping\n"); |
| return 0; |
| } |
| |
| fprintf(stderr, |
| "[gart] ring read ptr handle = 0x%08lx\n", |
| info->ringReadPtrHandle); |
| |
| if (drmAddMap(ctx->drmFD, info->bufStart, info->bufMapSize, |
| DRM_AGP, 0, &info->bufHandle) < 0) { |
| fprintf(stderr, |
| "[gart] Could not add vertex/indirect buffers mapping\n"); |
| return 0; |
| } |
| fprintf(stderr, |
| "[gart] vertex/indirect buffers handle = 0x%08x\n", |
| info->bufHandle); |
| |
| if (drmAddMap(ctx->drmFD, info->gartTexStart, info->gartTexMapSize, |
| DRM_AGP, 0, &info->gartTexHandle) < 0) { |
| fprintf(stderr, |
| "[gart] Could not add AGP texture map mapping\n"); |
| return 0; |
| } |
| fprintf(stderr, |
| "[gart] AGP texture map handle = 0x%08lx\n", |
| info->gartTexHandle); |
| |
| /* Initialize Radeon's AGP registers */ |
| /* Ring buffer is at AGP offset 0 */ |
| OUTREG(RADEON_AGP_BASE, info->ringHandle); |
| |
| return 1; |
| } |
| |
| /* Initialize the PCI GART state. Request memory for use in PCI space, |
| * and initialize the Radeon registers to point to that memory. |
| */ |
| static int RADEONDRIPciInit(const DRIDriverContext *ctx, RADEONInfoPtr info) |
| { |
| int ret; |
| int flags = DRM_READ_ONLY | DRM_LOCKED | DRM_KERNEL; |
| int s, l; |
| |
| ret = drmScatterGatherAlloc(ctx->drmFD, info->gartSize*1024*1024, |
| &info->gartMemHandle); |
| if (ret < 0) { |
| fprintf(stderr, "[pci] Out of memory (%d)\n", ret); |
| return 0; |
| } |
| fprintf(stderr, |
| "[pci] %d kB allocated with handle 0x%08lx\n", |
| info->gartSize*1024, info->gartMemHandle); |
| |
| info->gartOffset = 0; |
| |
| /* Initialize the CP ring buffer data */ |
| info->ringStart = info->gartOffset; |
| info->ringMapSize = info->ringSize*1024*1024 + radeon_drm_page_size; |
| |
| info->ringReadOffset = info->ringStart + info->ringMapSize; |
| info->ringReadMapSize = radeon_drm_page_size; |
| |
| /* Reserve space for vertex/indirect buffers */ |
| info->bufStart = info->ringReadOffset + info->ringReadMapSize; |
| info->bufMapSize = info->bufSize*1024*1024; |
| |
| /* Reserve the rest for AGP textures */ |
| info->gartTexStart = info->bufStart + info->bufMapSize; |
| s = (info->gartSize*1024*1024 - info->gartTexStart); |
| l = RADEONMinBits((s-1) / RADEON_NR_TEX_REGIONS); |
| if (l < RADEON_LOG_TEX_GRANULARITY) l = RADEON_LOG_TEX_GRANULARITY; |
| info->gartTexMapSize = (s >> l) << l; |
| info->log2GARTTexGran = l; |
| |
| if (drmAddMap(ctx->drmFD, info->ringStart, info->ringMapSize, |
| DRM_SCATTER_GATHER, flags, &info->ringHandle) < 0) { |
| fprintf(stderr, |
| "[pci] Could not add ring mapping\n"); |
| return 0; |
| } |
| fprintf(stderr, |
| "[pci] ring handle = 0x%08x\n", info->ringHandle); |
| |
| if (drmAddMap(ctx->drmFD, info->ringReadOffset, info->ringReadMapSize, |
| DRM_SCATTER_GATHER, flags, &info->ringReadPtrHandle) < 0) { |
| fprintf(stderr, |
| "[pci] Could not add ring read ptr mapping\n"); |
| return 0; |
| } |
| fprintf(stderr, |
| "[pci] ring read ptr handle = 0x%08lx\n", |
| info->ringReadPtrHandle); |
| |
| if (drmAddMap(ctx->drmFD, info->bufStart, info->bufMapSize, |
| DRM_SCATTER_GATHER, 0, &info->bufHandle) < 0) { |
| fprintf(stderr, |
| "[pci] Could not add vertex/indirect buffers mapping\n"); |
| return 0; |
| } |
| fprintf(stderr, |
| "[pci] vertex/indirect buffers handle = 0x%08lx\n", |
| info->bufHandle); |
| |
| if (drmAddMap(ctx->drmFD, info->gartTexStart, info->gartTexMapSize, |
| DRM_SCATTER_GATHER, 0, &info->gartTexHandle) < 0) { |
| fprintf(stderr, |
| "[pci] Could not add GART texture map mapping\n"); |
| return 0; |
| } |
| fprintf(stderr, |
| "[pci] GART texture map handle = 0x%08x\n", |
| info->gartTexHandle); |
| |
| return 1; |
| } |
| |
| |
| /** |
| * \brief Initialize the kernel data structures and enable the CP engine. |
| * |
| * \param ctx display handle. |
| * \param info driver private data. |
| * |
| * \return non-zero on success, or zero on failure. |
| * |
| * This function is a wrapper around the DRM_RADEON_CP_INIT command, passing |
| * all the parameters in a drm_radeon_init_t structure. |
| */ |
| static int RADEONDRIKernelInit( const DRIDriverContext *ctx, |
| RADEONInfoPtr info) |
| { |
| int cpp = ctx->bpp / 8; |
| drm_radeon_init_t drmInfo; |
| int ret; |
| |
| memset(&drmInfo, 0, sizeof(drm_radeon_init_t)); |
| |
| if ( (info->ChipFamily == CHIP_FAMILY_R200) || |
| (info->ChipFamily == CHIP_FAMILY_RV250) || |
| (info->ChipFamily == CHIP_FAMILY_M9) || |
| (info->ChipFamily == CHIP_FAMILY_RV280) ) |
| drmInfo.func = RADEON_INIT_R200_CP; |
| else |
| drmInfo.func = RADEON_INIT_CP; |
| |
| /* This is the struct passed to the kernel module for its initialization */ |
| drmInfo.sarea_priv_offset = sizeof(drm_sarea_t); |
| drmInfo.is_pci = ctx->isPCI; |
| drmInfo.cp_mode = RADEON_DEFAULT_CP_BM_MODE; |
| drmInfo.gart_size = info->gartSize*1024*1024; |
| drmInfo.ring_size = info->ringSize*1024*1024; |
| drmInfo.usec_timeout = 1000; |
| drmInfo.fb_bpp = ctx->bpp; |
| drmInfo.depth_bpp = ctx->bpp; |
| drmInfo.front_offset = info->frontOffset; |
| drmInfo.front_pitch = info->frontPitch * cpp; |
| drmInfo.back_offset = info->backOffset; |
| drmInfo.back_pitch = info->backPitch * cpp; |
| drmInfo.depth_offset = info->depthOffset; |
| drmInfo.depth_pitch = info->depthPitch * cpp; |
| drmInfo.fb_offset = info->LinearAddr; |
| drmInfo.mmio_offset = info->registerHandle; |
| drmInfo.ring_offset = info->ringHandle; |
| drmInfo.ring_rptr_offset = info->ringReadPtrHandle; |
| drmInfo.buffers_offset = info->bufHandle; |
| drmInfo.gart_textures_offset = info->gartTexHandle; |
| |
| ret = drmCommandWrite(ctx->drmFD, DRM_RADEON_CP_INIT, &drmInfo, |
| sizeof(drm_radeon_init_t)); |
| |
| return ret >= 0; |
| } |
| |
| |
| /** |
| * \brief Initialize the AGP heap. |
| * |
| * \param ctx display handle. |
| * \param info driver private data. |
| * |
| * This function is a wrapper around the DRM_RADEON_INIT_HEAP command, passing |
| * all the parameters in a drm_radeon_mem_init_heap structure. |
| */ |
| static void RADEONDRIAgpHeapInit(const DRIDriverContext *ctx, |
| RADEONInfoPtr info) |
| { |
| drm_radeon_mem_init_heap_t drmHeap; |
| |
| /* Start up the simple memory manager for gart space */ |
| drmHeap.region = RADEON_MEM_REGION_GART; |
| drmHeap.start = 0; |
| drmHeap.size = info->gartTexMapSize; |
| |
| if (drmCommandWrite(ctx->drmFD, DRM_RADEON_INIT_HEAP, |
| &drmHeap, sizeof(drmHeap))) { |
| fprintf(stderr, |
| "[drm] Failed to initialized gart heap manager\n"); |
| } else { |
| fprintf(stderr, |
| "[drm] Initialized kernel gart heap manager, %d\n", |
| info->gartTexMapSize); |
| } |
| } |
| |
| /** |
| * \brief Add a map for the vertex buffers that will be accessed by any |
| * DRI-based clients. |
| * |
| * \param ctx display handle. |
| * \param info driver private data. |
| * |
| * \return one on success, or zero on failure. |
| * |
| * Calls drmAddBufs() with the previously allocated vertex buffers. |
| */ |
| static int RADEONDRIBufInit( const DRIDriverContext *ctx, RADEONInfoPtr info ) |
| { |
| /* Initialize vertex buffers */ |
| info->bufNumBufs = drmAddBufs(ctx->drmFD, |
| info->bufMapSize / RADEON_BUFFER_SIZE, |
| RADEON_BUFFER_SIZE, |
| ctx->isPCI ? DRM_SG_BUFFER : DRM_AGP_BUFFER, |
| info->bufStart); |
| |
| if (info->bufNumBufs <= 0) { |
| fprintf(stderr, |
| "[drm] Could not create vertex/indirect buffers list\n"); |
| return 0; |
| } |
| fprintf(stderr, |
| "[drm] Added %d %d byte vertex/indirect buffers\n", |
| info->bufNumBufs, RADEON_BUFFER_SIZE); |
| |
| return 1; |
| } |
| |
| /** |
| * \brief Install an IRQ handler. |
| * |
| * \param ctx display handle. |
| * \param info driver private data. |
| * |
| * Attempts to install an IRQ handler via drmCtlInstHandler(), falling back to |
| * IRQ-free operation on failure. |
| */ |
| static void RADEONDRIIrqInit(const DRIDriverContext *ctx, |
| RADEONInfoPtr info) |
| { |
| if (!info->irq) { |
| info->irq = drmGetInterruptFromBusID(ctx->drmFD, |
| ctx->pciBus, |
| ctx->pciDevice, |
| ctx->pciFunc); |
| |
| if ((drmCtlInstHandler(ctx->drmFD, info->irq)) != 0) { |
| fprintf(stderr, |
| "[drm] failure adding irq handler, " |
| "there is a device already using that irq\n" |
| "[drm] falling back to irq-free operation\n"); |
| info->irq = 0; |
| } |
| } |
| |
| if (info->irq) |
| fprintf(stderr, |
| "[drm] dma control initialized, using IRQ %d\n", |
| info->irq); |
| } |
| |
| static int RADEONCheckDRMVersion( const DRIDriverContext *ctx, |
| RADEONInfoPtr info ) |
| { |
| drmVersionPtr version; |
| |
| version = drmGetVersion(ctx->drmFD); |
| if (version) { |
| int req_minor, req_patch; |
| |
| /* Need 1.8.x for proper cleanup-on-client-exit behaviour. |
| */ |
| req_minor = 8; |
| req_patch = 0; |
| |
| if (version->version_major != 1 || |
| version->version_minor < req_minor || |
| (version->version_minor == req_minor && |
| version->version_patchlevel < req_patch)) { |
| /* Incompatible drm version */ |
| fprintf(stderr, |
| "[dri] RADEONDRIScreenInit failed because of a version " |
| "mismatch.\n" |
| "[dri] radeon.o kernel module version is %d.%d.%d " |
| "but version 1.%d.%d or newer is needed.\n" |
| "[dri] Disabling DRI.\n", |
| version->version_major, |
| version->version_minor, |
| version->version_patchlevel, |
| req_minor, |
| req_patch); |
| drmFreeVersion(version); |
| return 0; |
| } |
| |
| info->drmMinor = version->version_minor; |
| drmFreeVersion(version); |
| } |
| |
| return 1; |
| } |
| |
| static int RADEONMemoryInit( const DRIDriverContext *ctx, RADEONInfoPtr info ) |
| { |
| int width_bytes = ctx->shared.virtualWidth * ctx->cpp; |
| int cpp = ctx->cpp; |
| int bufferSize = ((((ctx->shared.virtualHeight+15) & ~15) * width_bytes + RADEON_BUFFER_ALIGN) & ~RADEON_BUFFER_ALIGN); |
| int depthSize = ((((ctx->shared.virtualHeight+15) & ~15) * width_bytes |
| + RADEON_BUFFER_ALIGN) & ~RADEON_BUFFER_ALIGN); |
| int l; |
| |
| info->frontOffset = 0; |
| info->frontPitch = ctx->shared.virtualWidth; |
| |
| fprintf(stderr, |
| "Using %d MB AGP aperture\n", info->gartSize); |
| fprintf(stderr, |
| "Using %d MB for the ring buffer\n", info->ringSize); |
| fprintf(stderr, |
| "Using %d MB for vertex/indirect buffers\n", info->bufSize); |
| fprintf(stderr, |
| "Using %d MB for AGP textures\n", info->gartTexSize); |
| |
| /* Front, back and depth buffers - everything else texture?? |
| */ |
| info->textureSize = ctx->shared.fbSize - 2 * bufferSize - depthSize; |
| |
| if (ctx->colorTiling==1) |
| { |
| info->textureSize = ctx->shared.fbSize - ((ctx->shared.fbSize - info->textureSize + width_bytes * 16 - 1) / (width_bytes * 16)) * (width_bytes*16); |
| } |
| |
| if (info->textureSize < 0) |
| return 0; |
| |
| l = RADEONMinBits((info->textureSize-1) / RADEON_NR_TEX_REGIONS); |
| if (l < RADEON_LOG_TEX_GRANULARITY) l = RADEON_LOG_TEX_GRANULARITY; |
| |
| /* Round the texture size up to the nearest whole number of |
| * texture regions. Again, be greedy about this, don't |
| * round down. |
| */ |
| info->log2TexGran = l; |
| info->textureSize = (info->textureSize >> l) << l; |
| |
| /* Set a minimum usable local texture heap size. This will fit |
| * two 256x256x32bpp textures. |
| */ |
| if (info->textureSize < 512 * 1024) { |
| info->textureOffset = 0; |
| info->textureSize = 0; |
| } |
| |
| /* Reserve space for textures */ |
| if (ctx->colorTiling==1) |
| { |
| info->textureOffset = ((ctx->shared.fbSize - info->textureSize) / |
| (width_bytes * 16)) * (width_bytes*16); |
| } |
| else |
| { |
| info->textureOffset = ((ctx->shared.fbSize - info->textureSize + |
| RADEON_BUFFER_ALIGN) & |
| ~RADEON_BUFFER_ALIGN); |
| } |
| /* Reserve space for the shared depth |
| * buffer. |
| */ |
| info->depthOffset = ((info->textureOffset - depthSize + |
| RADEON_BUFFER_ALIGN) & |
| ~RADEON_BUFFER_ALIGN); |
| info->depthPitch = ctx->shared.virtualWidth; |
| |
| info->backOffset = ((info->depthOffset - bufferSize + |
| RADEON_BUFFER_ALIGN) & |
| ~RADEON_BUFFER_ALIGN); |
| info->backPitch = ctx->shared.virtualWidth; |
| |
| |
| fprintf(stderr, |
| "Will use back buffer at offset 0x%x\n", |
| info->backOffset); |
| fprintf(stderr, |
| "Will use depth buffer at offset 0x%x\n", |
| info->depthOffset); |
| fprintf(stderr, |
| "Will use %d kb for textures at offset 0x%x\n", |
| info->textureSize/1024, info->textureOffset); |
| |
| info->frontPitchOffset = (((info->frontPitch * cpp / 64) << 22) | |
| (info->frontOffset >> 10)); |
| |
| info->backPitchOffset = (((info->backPitch * cpp / 64) << 22) | |
| (info->backOffset >> 10)); |
| |
| info->depthPitchOffset = (((info->depthPitch * cpp / 64) << 22) | |
| (info->depthOffset >> 10)); |
| |
| return 1; |
| } |
| |
| static int RADEONColorTilingInit( const DRIDriverContext *ctx, RADEONInfoPtr info ) |
| { |
| int width_bytes = ctx->shared.virtualWidth * ctx->cpp; |
| int bufferSize = ((((ctx->shared.virtualHeight+15) & ~15) * width_bytes + RADEON_BUFFER_ALIGN) |
| & ~RADEON_BUFFER_ALIGN); |
| /* Setup color tiling */ |
| if (info->drmMinor<14) |
| info->colorTiling=0; |
| |
| if (info->colorTiling) |
| { |
| |
| int colorTilingFlag; |
| drm_radeon_surface_alloc_t front,back; |
| |
| RadeonSetParam(ctx, RADEON_SETPARAM_SWITCH_TILING, info->colorTiling ? 1 : 0); |
| |
| /* Setup the surfaces */ |
| if (info->ChipFamily < CHIP_FAMILY_R200) |
| colorTilingFlag=RADEON_SURF_TILE_COLOR_MACRO; |
| else |
| colorTilingFlag=R200_SURF_TILE_COLOR_MACRO; |
| |
| front.address = info->frontOffset; |
| front.size = bufferSize; |
| front.flags = (width_bytes) | colorTilingFlag; |
| drmCommandWrite(ctx->drmFD, DRM_RADEON_SURF_ALLOC, &front,sizeof(front)); |
| |
| back.address = info->backOffset; |
| back.size = bufferSize; |
| back.flags = (width_bytes) | colorTilingFlag; |
| drmCommandWrite(ctx->drmFD, DRM_RADEON_SURF_ALLOC, &back,sizeof(back)); |
| |
| } |
| return 1; |
| } |
| |
| |
| |
| /** |
| * Called at the start of each server generation. |
| * |
| * \param ctx display handle. |
| * \param info driver private data. |
| * |
| * \return non-zero on success, or zero on failure. |
| * |
| * Performs static frame buffer allocation. Opens the DRM device and add maps |
| * to the SAREA, framebuffer and MMIO regions. Fills in \p info with more |
| * information. Creates a \e server context to grab the lock for the |
| * initialization ioctls and calls the other initilization functions in this |
| * file. Starts the CP engine via the DRM_RADEON_CP_START command. |
| * |
| * Setups a RADEONDRIRec structure to be passed to radeon_dri.so for its |
| * initialization. |
| */ |
| static int RADEONScreenInit( DRIDriverContext *ctx, RADEONInfoPtr info ) |
| { |
| RADEONDRIPtr pRADEONDRI; |
| int err; |
| |
| usleep(100); |
| /*assert(!ctx->IsClient);*/ |
| |
| { |
| int width_bytes = (ctx->shared.virtualWidth * ctx->cpp); |
| int maxy = ctx->shared.fbSize / width_bytes; |
| |
| |
| if (maxy <= ctx->shared.virtualHeight * 3) { |
| fprintf(stderr, |
| "Static buffer allocation failed -- " |
| "need at least %d kB video memory (have %d kB)\n", |
| (ctx->shared.virtualWidth * ctx->shared.virtualHeight * |
| ctx->cpp * 3 + 1023) / 1024, |
| ctx->shared.fbSize / 1024); |
| return 0; |
| } |
| } |
| |
| |
| if (info->ChipFamily >= CHIP_FAMILY_R300) { |
| fprintf(stderr, |
| "Direct rendering not yet supported on " |
| "Radeon 9700 and newer cards\n"); |
| return 0; |
| } |
| |
| radeon_drm_page_size = getpagesize(); |
| |
| info->registerSize = ctx->MMIOSize; |
| ctx->shared.SAREASize = SAREA_MAX; |
| |
| /* Note that drmOpen will try to load the kernel module, if needed. */ |
| ctx->drmFD = drmOpen("radeon", NULL ); |
| if (ctx->drmFD < 0) { |
| fprintf(stderr, "[drm] drmOpen failed\n"); |
| return 0; |
| } |
| |
| if ((err = drmSetBusid(ctx->drmFD, ctx->pciBusID)) < 0) { |
| fprintf(stderr, "[drm] drmSetBusid failed (%d, %s), %s\n", |
| ctx->drmFD, ctx->pciBusID, strerror(-err)); |
| return 0; |
| } |
| |
| if (drmAddMap( ctx->drmFD, |
| 0, |
| ctx->shared.SAREASize, |
| DRM_SHM, |
| DRM_CONTAINS_LOCK, |
| &ctx->shared.hSAREA) < 0) |
| { |
| fprintf(stderr, "[drm] drmAddMap failed\n"); |
| return 0; |
| } |
| fprintf(stderr, "[drm] added %d byte SAREA at 0x%08lx\n", |
| ctx->shared.SAREASize, ctx->shared.hSAREA); |
| |
| if (drmMap( ctx->drmFD, |
| ctx->shared.hSAREA, |
| ctx->shared.SAREASize, |
| (drmAddressPtr)(&ctx->pSAREA)) < 0) |
| { |
| fprintf(stderr, "[drm] drmMap failed\n"); |
| return 0; |
| } |
| memset(ctx->pSAREA, 0, ctx->shared.SAREASize); |
| fprintf(stderr, "[drm] mapped SAREA 0x%08lx to %p, size %d\n", |
| ctx->shared.hSAREA, ctx->pSAREA, ctx->shared.SAREASize); |
| |
| /* Need to AddMap the framebuffer and mmio regions here: |
| */ |
| if (drmAddMap( ctx->drmFD, |
| (drm_handle_t)ctx->FBStart, |
| ctx->FBSize, |
| DRM_FRAME_BUFFER, |
| #ifndef _EMBEDDED |
| 0, |
| #else |
| DRM_READ_ONLY, |
| #endif |
| &ctx->shared.hFrameBuffer) < 0) |
| { |
| fprintf(stderr, "[drm] drmAddMap framebuffer failed\n"); |
| return 0; |
| } |
| |
| fprintf(stderr, "[drm] framebuffer handle = 0x%08lx\n", |
| ctx->shared.hFrameBuffer); |
| |
| |
| |
| if (drmAddMap(ctx->drmFD, |
| ctx->MMIOStart, |
| ctx->MMIOSize, |
| DRM_REGISTERS, |
| DRM_READ_ONLY, |
| &info->registerHandle) < 0) { |
| fprintf(stderr, "[drm] drmAddMap mmio failed\n"); |
| return 0; |
| } |
| fprintf(stderr, |
| "[drm] register handle = 0x%08lx\n", info->registerHandle); |
| |
| /* Check the radeon DRM version */ |
| if (!RADEONCheckDRMVersion(ctx, info)) { |
| return 0; |
| } |
| |
| if (ctx->isPCI) { |
| /* Initialize PCI */ |
| if (!RADEONDRIPciInit(ctx, info)) |
| return 0; |
| } |
| else { |
| /* Initialize AGP */ |
| if (!RADEONDRIAgpInit(ctx, info)) |
| return 0; |
| } |
| |
| /* Memory manager setup */ |
| if (!RADEONMemoryInit(ctx, info)) { |
| return 0; |
| } |
| |
| /* Create a 'server' context so we can grab the lock for |
| * initialization ioctls. |
| */ |
| if ((err = drmCreateContext(ctx->drmFD, &ctx->serverContext)) != 0) { |
| fprintf(stderr, "%s: drmCreateContext failed %d\n", __FUNCTION__, err); |
| return 0; |
| } |
| |
| DRM_LOCK(ctx->drmFD, ctx->pSAREA, ctx->serverContext, 0); |
| |
| /* Initialize the kernel data structures */ |
| if (!RADEONDRIKernelInit(ctx, info)) { |
| fprintf(stderr, "RADEONDRIKernelInit failed\n"); |
| DRM_UNLOCK(ctx->drmFD, ctx->pSAREA, ctx->serverContext); |
| return 0; |
| } |
| |
| /* Initialize the vertex buffers list */ |
| if (!RADEONDRIBufInit(ctx, info)) { |
| fprintf(stderr, "RADEONDRIBufInit failed\n"); |
| DRM_UNLOCK(ctx->drmFD, ctx->pSAREA, ctx->serverContext); |
| return 0; |
| } |
| |
| RADEONColorTilingInit(ctx, info); |
| |
| /* Initialize IRQ */ |
| RADEONDRIIrqInit(ctx, info); |
| |
| /* Initialize kernel gart memory manager */ |
| RADEONDRIAgpHeapInit(ctx, info); |
| |
| fprintf(stderr,"color tiling %sabled\n", info->colorTiling?"en":"dis"); |
| fprintf(stderr,"page flipping %sabled\n", info->page_flip_enable?"en":"dis"); |
| /* Initialize the SAREA private data structure */ |
| { |
| drm_radeon_sarea_t *pSAREAPriv; |
| pSAREAPriv = (drm_radeon_sarea_t *)(((char*)ctx->pSAREA) + |
| sizeof(drm_sarea_t)); |
| memset(pSAREAPriv, 0, sizeof(*pSAREAPriv)); |
| pSAREAPriv->pfState = info->page_flip_enable; |
| } |
| |
| |
| /* Quick hack to clear the front & back buffers. Could also use |
| * the clear ioctl to do this, but would need to setup hw state |
| * first. |
| */ |
| drimemsetio((char *)ctx->FBAddress + info->frontOffset, |
| 0, |
| info->frontPitch * ctx->cpp * ctx->shared.virtualHeight ); |
| |
| drimemsetio((char *)ctx->FBAddress + info->backOffset, |
| 0, |
| info->backPitch * ctx->cpp * ctx->shared.virtualHeight ); |
| |
| /* This is the struct passed to radeon_dri.so for its initialization */ |
| ctx->driverClientMsg = malloc(sizeof(RADEONDRIRec)); |
| ctx->driverClientMsgSize = sizeof(RADEONDRIRec); |
| pRADEONDRI = (RADEONDRIPtr)ctx->driverClientMsg; |
| pRADEONDRI->deviceID = info->Chipset; |
| pRADEONDRI->width = ctx->shared.virtualWidth; |
| pRADEONDRI->height = ctx->shared.virtualHeight; |
| pRADEONDRI->depth = ctx->bpp; /* XXX: depth */ |
| pRADEONDRI->bpp = ctx->bpp; |
| pRADEONDRI->IsPCI = ctx->isPCI; |
| pRADEONDRI->AGPMode = ctx->agpmode; |
| pRADEONDRI->frontOffset = info->frontOffset; |
| pRADEONDRI->frontPitch = info->frontPitch; |
| pRADEONDRI->backOffset = info->backOffset; |
| pRADEONDRI->backPitch = info->backPitch; |
| pRADEONDRI->depthOffset = info->depthOffset; |
| pRADEONDRI->depthPitch = info->depthPitch; |
| pRADEONDRI->textureOffset = info->textureOffset; |
| pRADEONDRI->textureSize = info->textureSize; |
| pRADEONDRI->log2TexGran = info->log2TexGran; |
| pRADEONDRI->registerHandle = info->registerHandle; |
| pRADEONDRI->registerSize = info->registerSize; |
| pRADEONDRI->statusHandle = info->ringReadPtrHandle; |
| pRADEONDRI->statusSize = info->ringReadMapSize; |
| pRADEONDRI->gartTexHandle = info->gartTexHandle; |
| pRADEONDRI->gartTexMapSize = info->gartTexMapSize; |
| pRADEONDRI->log2GARTTexGran = info->log2GARTTexGran; |
| pRADEONDRI->gartTexOffset = info->gartTexStart; |
| pRADEONDRI->sarea_priv_offset = sizeof(drm_sarea_t); |
| |
| /* Don't release the lock now - let the VT switch handler do it. */ |
| |
| return 1; |
| } |
| |
| |
| /** |
| * \brief Get Radeon chip family from chipset number. |
| * |
| * \param info driver private data. |
| * |
| * \return non-zero on success, or zero on failure. |
| * |
| * Called by radeonInitFBDev() to set RADEONInfoRec::ChipFamily |
| * according to the value of RADEONInfoRec::Chipset. Fails if the |
| * chipset is unrecognized or not appropriate for this driver (i.e., not |
| * an r100 style radeon) |
| */ |
| static int get_chipfamily_from_chipset( RADEONInfoPtr info ) |
| { |
| switch (info->Chipset) { |
| case PCI_CHIP_RADEON_LY: |
| case PCI_CHIP_RADEON_LZ: |
| info->ChipFamily = CHIP_FAMILY_M6; |
| break; |
| |
| case PCI_CHIP_RADEON_QY: |
| case PCI_CHIP_RADEON_QZ: |
| info->ChipFamily = CHIP_FAMILY_VE; |
| break; |
| |
| case PCI_CHIP_R200_QL: |
| case PCI_CHIP_R200_QN: |
| case PCI_CHIP_R200_QO: |
| case PCI_CHIP_R200_Ql: |
| case PCI_CHIP_R200_BB: |
| info->ChipFamily = CHIP_FAMILY_R200; |
| break; |
| |
| case PCI_CHIP_RV200_QW: /* RV200 desktop */ |
| case PCI_CHIP_RV200_QX: |
| info->ChipFamily = CHIP_FAMILY_RV200; |
| break; |
| |
| case PCI_CHIP_RADEON_LW: |
| case PCI_CHIP_RADEON_LX: |
| info->ChipFamily = CHIP_FAMILY_M7; |
| break; |
| |
| case PCI_CHIP_RV250_Id: |
| case PCI_CHIP_RV250_Ie: |
| case PCI_CHIP_RV250_If: |
| case PCI_CHIP_RV250_Ig: |
| info->ChipFamily = CHIP_FAMILY_RV250; |
| break; |
| |
| case PCI_CHIP_RV250_Ld: |
| case PCI_CHIP_RV250_Le: |
| case PCI_CHIP_RV250_Lf: |
| case PCI_CHIP_RV250_Lg: |
| info->ChipFamily = CHIP_FAMILY_M9; |
| break; |
| |
| case PCI_CHIP_RV280_Y_: |
| case PCI_CHIP_RV280_Ya: |
| case PCI_CHIP_RV280_Yb: |
| case PCI_CHIP_RV280_Yc: |
| info->ChipFamily = CHIP_FAMILY_RV280; |
| break; |
| |
| case PCI_CHIP_R300_ND: |
| case PCI_CHIP_R300_NE: |
| case PCI_CHIP_R300_NF: |
| case PCI_CHIP_R300_NG: |
| info->ChipFamily = CHIP_FAMILY_R300; |
| break; |
| |
| default: |
| /* Original Radeon/7200 */ |
| info->ChipFamily = CHIP_FAMILY_RADEON; |
| } |
| |
| return 1; |
| } |
| |
| |
| /** |
| * \brief Validate the fbdev mode. |
| * |
| * \param ctx display handle. |
| * |
| * \return one on success, or zero on failure. |
| * |
| * Saves some registers and returns 1. |
| * |
| * \sa radeonValidateMode(). |
| */ |
| static int radeonValidateMode( const DRIDriverContext *ctx ) |
| { |
| unsigned char *RADEONMMIO = ctx->MMIOAddress; |
| RADEONInfoPtr info = ctx->driverPrivate; |
| |
| info->gen_int_cntl = INREG(RADEON_GEN_INT_CNTL); |
| info->crtc_offset_cntl = INREG(RADEON_CRTC_OFFSET_CNTL); |
| |
| if (info->colorTiling) |
| info->crtc_offset_cntl |= RADEON_CRTC_TILE_EN; |
| return 1; |
| } |
| |
| |
| /** |
| * \brief Examine mode returned by fbdev. |
| * |
| * \param ctx display handle. |
| * |
| * \return one on success, or zero on failure. |
| * |
| * Restores registers that fbdev has clobbered and returns 1. |
| * |
| * \sa radeonValidateMode(). |
| */ |
| static int radeonPostValidateMode( const DRIDriverContext *ctx ) |
| { |
| unsigned char *RADEONMMIO = ctx->MMIOAddress; |
| RADEONInfoPtr info = ctx->driverPrivate; |
| |
| RADEONColorTilingInit( ctx, info); |
| OUTREG(RADEON_GEN_INT_CNTL, info->gen_int_cntl); |
| if (info->colorTiling) |
| info->crtc_offset_cntl |= RADEON_CRTC_TILE_EN; |
| OUTREG(RADEON_CRTC_OFFSET_CNTL, info->crtc_offset_cntl); |
| |
| return 1; |
| } |
| |
| |
| /** |
| * \brief Initialize the framebuffer device mode |
| * |
| * \param ctx display handle. |
| * |
| * \return one on success, or zero on failure. |
| * |
| * Fills in \p info with some default values and some information from \p ctx |
| * and then calls RADEONScreenInit() for the screen initialization. |
| * |
| * Before exiting clears the framebuffer memory accessing it directly. |
| */ |
| static int radeonInitFBDev( DRIDriverContext *ctx ) |
| { |
| RADEONInfoPtr info = calloc(1, sizeof(*info)); |
| |
| { |
| int dummy = ctx->shared.virtualWidth; |
| |
| if (ctx->colorTiling==1) |
| { |
| switch (ctx->bpp / 8) { |
| case 1: dummy = (ctx->shared.virtualWidth + 255) & ~255; break; |
| case 2: dummy = (ctx->shared.virtualWidth + 127) & ~127; break; |
| case 3: |
| case 4: dummy = (ctx->shared.virtualWidth + 63) & ~63; break; |
| } |
| } else { |
| switch (ctx->bpp / 8) { |
| case 1: dummy = (ctx->shared.virtualWidth + 127) & ~127; break; |
| case 2: dummy = (ctx->shared.virtualWidth + 31) & ~31; break; |
| case 3: |
| case 4: dummy = (ctx->shared.virtualWidth + 15) & ~15; break; |
| } |
| } |
| |
| ctx->shared.virtualWidth = dummy; |
| ctx->shared.Width = dummy; |
| } |
| |
| fprintf(stderr,"shared virtual width is %d\n", ctx->shared.virtualWidth); |
| ctx->driverPrivate = (void *)info; |
| |
| info->gartFastWrite = RADEON_DEFAULT_AGP_FAST_WRITE; |
| info->gartSize = RADEON_DEFAULT_AGP_SIZE; |
| info->gartTexSize = RADEON_DEFAULT_AGP_TEX_SIZE; |
| info->bufSize = RADEON_DEFAULT_BUFFER_SIZE; |
| info->ringSize = RADEON_DEFAULT_RING_SIZE; |
| info->page_flip_enable = RADEON_DEFAULT_PAGE_FLIP; |
| info->colorTiling = ctx->colorTiling; |
| |
| info->Chipset = ctx->chipset; |
| |
| if (!get_chipfamily_from_chipset( info )) { |
| fprintf(stderr, "Unknown or non-radeon chipset -- cannot continue\n"); |
| fprintf(stderr, "==> Verify PCI BusID is correct in miniglx.conf\n"); |
| return 0; |
| } |
| |
| info->frontPitch = ctx->shared.virtualWidth; |
| info->LinearAddr = ctx->FBStart & 0xfc000000; |
| |
| |
| if (!RADEONScreenInit( ctx, info )) |
| return 0; |
| |
| |
| return 1; |
| } |
| |
| |
| /** |
| * \brief The screen is being closed, so clean up any state and free any |
| * resources used by the DRI. |
| * |
| * \param ctx display handle. |
| * |
| * Unmaps the SAREA, closes the DRM device file descriptor and frees the driver |
| * private data. |
| */ |
| static void radeonHaltFBDev( DRIDriverContext *ctx ) |
| { |
| drmUnmap( ctx->pSAREA, ctx->shared.SAREASize ); |
| drmClose(ctx->drmFD); |
| |
| if (ctx->driverPrivate) { |
| free(ctx->driverPrivate); |
| ctx->driverPrivate = 0; |
| } |
| } |
| |
| |
| extern void radeonNotifyFocus( int ); |
| |
| /** |
| * \brief Exported driver interface for Mini GLX. |
| * |
| * \sa DRIDriverRec. |
| */ |
| const struct DRIDriverRec __driDriver = { |
| radeonValidateMode, |
| radeonPostValidateMode, |
| radeonInitFBDev, |
| radeonHaltFBDev, |
| RADEONEngineShutdown, |
| RADEONEngineRestore, |
| #ifndef _EMBEDDED |
| 0, |
| #else |
| radeonNotifyFocus, |
| #endif |
| }; |