/* Shut down the PVR chip from ready status, leaving it in 2D mode as it
   was before the init. */
int pvr_shutdown() {
    if(!pvr_state.valid)
        return -1;

    /* Set us invalid */
    pvr_state.valid = 0;

    /* Stop anything that might be going on */
    PVR_SET(PVR_RESET, PVR_RESET_ALL);
    PVR_SET(PVR_RESET, PVR_RESET_NONE);

    /* Unhook any int handlers */
    vblank_handler_remove(pvr_state.vbl_handle);
    asic_evt_set_handler(ASIC_EVT_PVR_OPAQUEDONE, NULL);
    asic_evt_disable(ASIC_EVT_PVR_OPAQUEDONE, ASIC_IRQ_DEFAULT);
    asic_evt_set_handler(ASIC_EVT_PVR_OPAQUEMODDONE, NULL);
    asic_evt_disable(ASIC_EVT_PVR_OPAQUEMODDONE, ASIC_IRQ_DEFAULT);
    asic_evt_set_handler(ASIC_EVT_PVR_TRANSDONE, NULL);
    asic_evt_disable(ASIC_EVT_PVR_TRANSDONE, ASIC_IRQ_DEFAULT);
    asic_evt_set_handler(ASIC_EVT_PVR_TRANSMODDONE, NULL);
    asic_evt_disable(ASIC_EVT_PVR_TRANSMODDONE, ASIC_IRQ_DEFAULT);
    asic_evt_set_handler(ASIC_EVT_PVR_PTDONE, NULL);
    asic_evt_disable(ASIC_EVT_PVR_PTDONE, ASIC_IRQ_DEFAULT);
    asic_evt_set_handler(ASIC_EVT_PVR_RENDERDONE, NULL);
    asic_evt_disable(ASIC_EVT_PVR_RENDERDONE, ASIC_IRQ_DEFAULT);

    /* Shut down PVR DMA */
    pvr_dma_shutdown();

    /* Invalidate our memory pool */
    pvr_mem_reset();

    /* Destroy the semaphore */
    sem_destroy((semaphore_t *)&pvr_state.ready_sem);
    mutex_destroy((mutex_t *)&pvr_state.dma_lock);

    /* Clear video memory */
    vid_empty();

    /* Reset the frame buffer offset */
    vid_waitvbl();
    vid_set_start(0);

    /* Return success */
    return 0;
}
Beispiel #2
0
/* Initialize the PVR chip to ready status, enabling the specified lists
   and using the specified parameters; note that bins and vertex buffers
   come from the texture memory pool! Expects that a 2D mode was 
   initialized already using the vid_* API. */
int pvr_init(pvr_init_params_t *params) {
	/* If we're already initialized, fail */
	if (pvr_state.valid == 1) {
		dbglog(DBG_WARNING, "pvr: pvr_init called twice!\n");
		return -1;
	}

	/* Make sure we got valid parameters */
	assert(params != NULL);

	/* Make sure that a video mode has been initialized */
	assert(vid_mode != NULL);
	assert(vid_mode->width != 0 && vid_mode->height != 0);

	/* Check for compatibility with 3D stuff */
	if ((vid_mode->width % 32) != 0) {
		dbglog(DBG_WARNING, "pvr: mode %dx%d isn't usable for 3D (width not multiples of 32)\n",
			vid_mode->width, vid_mode->height);
		return -1;
	}

	/* Clear out video memory */
	vid_empty();

	/* Reset all PVR systems (in case it's still doing something) */
	PVR_SET(PVR_RESET, PVR_RESET_ALL);
	PVR_SET(PVR_RESET, PVR_RESET_NONE);

	/* Start off with a nice empty structure */
	memset((void *)&pvr_state, 0, sizeof(pvr_state));

	// Enable DMA if the user wants that.
	pvr_state.dma_mode = params->dma_enabled;

	/* Everything's clear, do the initial buffer pointer setup */
	pvr_allocate_buffers(params);

	// Initialize tile matrices
	pvr_init_tile_matrices();

	// Setup all pipeline targets. Yes, this is redundant. :) I just
	// like to have it explicit.
	pvr_state.ram_target = 0;
	pvr_state.ta_target = 0;
	pvr_state.view_target = 0;
	
	pvr_state.list_reg_open = -1;

	// Sync all the hardware registers with our pipeline state.
	pvr_sync_view();
	pvr_sync_reg_buffer();

	// Clear out our stats
	pvr_state.vbl_count = 0;
	pvr_state.frame_last_time = 0;
	pvr_state.buf_start_time = 0;
	pvr_state.reg_start_time = 0;
	pvr_state.rnd_start_time = 0;
	pvr_state.frame_last_len = -1;
	pvr_state.buf_last_len = -1;
	pvr_state.reg_last_len = -1;
	pvr_state.rnd_last_len = -1;
	pvr_state.vtx_buf_used = 0;
	pvr_state.vtx_buf_used_max = 0;

	/* If we're on a VGA box, disable vertical smoothing */
	if (vid_mode->cable_type == CT_VGA) {
		dbglog(DBG_KDEBUG, "pvr: disabling vertical scaling for VGA\n");
		PVR_SET(PVR_SCALER_CFG, 0x400);
	} else {
		dbglog(DBG_KDEBUG, "pvr: enabling vertical scaling for non-VGA\n");
		PVR_SET(PVR_SCALER_CFG, 0x401);
	}

	/* Hook the PVR interrupt events on G2 */
	pvr_state.vbl_handle = vblank_handler_add(pvr_int_handler);
	asic_evt_set_handler(ASIC_EVT_PVR_OPAQUEDONE, pvr_int_handler);		asic_evt_enable(ASIC_EVT_PVR_OPAQUEDONE, ASIC_IRQ_DEFAULT);
	asic_evt_set_handler(ASIC_EVT_PVR_OPAQUEMODDONE, pvr_int_handler);	asic_evt_enable(ASIC_EVT_PVR_OPAQUEMODDONE, ASIC_IRQ_DEFAULT);
	asic_evt_set_handler(ASIC_EVT_PVR_TRANSDONE, pvr_int_handler);		asic_evt_enable(ASIC_EVT_PVR_TRANSDONE, ASIC_IRQ_DEFAULT);
	asic_evt_set_handler(ASIC_EVT_PVR_TRANSMODDONE, pvr_int_handler);	asic_evt_enable(ASIC_EVT_PVR_TRANSMODDONE, ASIC_IRQ_DEFAULT);
	asic_evt_set_handler(ASIC_EVT_PVR_PTDONE, pvr_int_handler);		asic_evt_enable(ASIC_EVT_PVR_PTDONE, ASIC_IRQ_DEFAULT);
	asic_evt_set_handler(ASIC_EVT_PVR_RENDERDONE, pvr_int_handler);		asic_evt_enable(ASIC_EVT_PVR_RENDERDONE, ASIC_IRQ_DEFAULT);

	/* 3d-specific parameters; these are all about rendering and
	   nothing to do with setting up the video; some stuff in here
	   is still unknown. */
   	PVR_SET(PVR_UNK_00A8, 0x15d1c951);		/* M (Unknown magic value) */
   	PVR_SET(PVR_UNK_00A0, 0x00000020);		/* M */
   	PVR_SET(PVR_FB_CFG_2, 0x00000009);		/* alpha config */
	PVR_SET(PVR_UNK_0110, 0x00093f39);		/* M */
	PVR_SET(PVR_UNK_0098, 0x00800408);		/* M */
	PVR_SET(PVR_TEXTURE_CLIP, 0x00000000);		/* texture clip distance */
	PVR_SET(PVR_SPANSORT_CFG, 0x00000101);		/* M */
	PVR_SET(PVR_FOG_TABLE_COLOR, 0x007f7f7f);	/* Fog table color */
	PVR_SET(PVR_FOG_VERTEX_COLOR, 0x007f7f7f);	/* Fog vertex color */
	PVR_SET(PVR_COLOR_CLAMP_MIN, 0x00000000);	/* color clamp min */
	PVR_SET(PVR_COLOR_CLAMP_MAX, 0xffffffff);	/* color clamp max */
	PVR_SET(PVR_UNK_0080, 0x00000007);		/* M */
	PVR_SET(PVR_CHEAP_SHADOW, 0x00000001);		/* cheap shadow */
	PVR_SET(PVR_UNK_007C, 0x0027df77);		/* M */
	PVR_SET(PVR_TEXTURE_MODULO, 0x00000000);	/* stride width */
	PVR_SET(PVR_FOG_DENSITY, 0x0000ff07);		/* fog density */
	PVR_SET(PVR_UNK_00C8, PVR_GET(0x00d4) << 16);	/* M */
	PVR_SET(PVR_UNK_0118, 0x00008040);		/* M */

	/* Initialize PVR DMA */
	pvr_state.dma_lock = mutex_create();
	pvr_dma_init();

	/* Setup our wait-ready semaphore */
	pvr_state.ready_sem = sem_create(0);

	/* Set us as valid and return success */
	pvr_state.valid = 1;

	/* Validate our memory pool */
	pvr_mem_reset();
/* This doesn't work right now... */
/*#ifndef NDEBUG
	dbglog(DBG_KDEBUG, "pvr: free memory is %08lx bytes\n",
		pvr_mem_available());
#endif*//* !NDEBUG */

	return 0;
}