Esempio n. 1
0
/*!
 * Get the stride and stereo values based on the display.  This is also used
 * by the MI instructions.
 *
 * @param display Pointer to hardware device instance data
 * @param stride
 * @param stereo
 * @param flags Should the stereo be for the frontbuffer or backbuffer?
 *
 * @return stride - Stride of the display
 * @return stereo - Stereo address of the display
 */
static int mode_get_stride_stereo_plb(igd_display_context_t *display,
	unsigned long *stride,
	unsigned long *stereo,
	unsigned long flags)
{
	unsigned long pitch = PLANE(display)->fb_info->screen_pitch;
	igd_timing_info_t *timing = PIPE(display)->timing;
	unsigned long base_offset;

	base_offset = PLANE(display)->fb_info->visible_offset;

	*stride = pitch;
	*stereo = 0;

	/* For field replication, valid for interlaced modes only
	 *     set stereo = fb_base,
	 *         stride = pitch
	 */
	if (timing->mode_info_flags & IGD_SCAN_INTERLACE) {

		if(timing->mode_info_flags & IGD_LINE_DOUBLE) {
			/* Interlaced + Line double flags means field replication.
			 * same lines are sent for both fields. Program the
			 * second eye to be same as the first.
			 */
			*stereo = base_offset;
		} else {
			/* Regular interlaced. Second eye starts on line 2.
			 * Skip every other line.
			 */
			*stereo = base_offset + pitch;
			*stride = pitch * 2;
		}
	}

	return 0;
}
Esempio n. 2
0
/*!
 * Program Display Plane Values.
 *
 * @param display Pointer to hardware device instance data
 * @param status
 *
 * @return void
 */
static void program_plane_plb(igd_display_context_t *display,
	unsigned long status)
{
	unsigned long stereo;
	unsigned long stride;
	unsigned long size;
	unsigned long plane_control;
	igd_timing_info_t *timing;
	igd_framebuffer_info_t *fb_info = PLANE(display)->fb_info;
	unsigned long plane_reg = PLANE(display)->plane_reg;
	unsigned long start_addr_reg = DSPAADDR;

	EMGD_TRACE_ENTER;

	EMGD_DEBUG("Program Plane: %s", status?"ENABLE":"DISABLE");
	EMGD_DEBUG("Device power state: D%ld", GET_DEVICE_POWER_STATE(display));

	igd_wait_vblank_plb((igd_display_h)display);

	plane_control = EMGD_READ32(MMIO(display) + plane_reg);
	if(PLANE(display)->plane_reg == DSPACNTR) {
		plane_control &= device_data->plane_a_preserve;
	}
	else { /* if it's plane b or plane c */
		plane_control &= device_data->plane_b_c_preserve;
		start_addr_reg = 0x71184;
	}

	if((status == FALSE) ||
		(GET_DEVICE_POWER_STATE(display) != IGD_POWERSTATE_D0)) {

		/*
		 * Note: The vga programming code does not have an "off". So
		 * when programming the plane to off we make sure VGA is off
		 * as well.
		 */
		disable_vga_plb(MMIO(display));

		/*
		 * To turn off plane A or B, the program have to triger the plane A or B
		 * start register.  Or else, it will not work.
		 */
		EMGD_WRITE32(plane_control, MMIO(display) + plane_reg);
		EMGD_WRITE32(EMGD_READ32(MMIO(display) + start_addr_reg),
			MMIO(display) + start_addr_reg);

		igd_wait_vblank_plb((igd_display_h)display);
		return;
	}
	/*
	 * Note: The very first pass through this function will be with
	 * status false and timings == NULL. Don't use the timings before
	 * the check above.
	 */
	timing = PIPE(display)->timing;
	/* There is a special case code for legacy VGA modes */
	while (timing->extn_ptr) {
		timing = (igd_timing_info_t *)timing->extn_ptr;
	}
	if(MODE_IS_VGA(timing)) {
		program_plane_vga(display, timing);
		return;
	}

	disable_vga_plb(MMIO(display));

	size = (((unsigned long)timing->height - 1)<<16) |
		(unsigned long)(timing->width - 1);

	/* enable plane, select pipe, enable gamma correction logic */
	plane_control |= 0x80000000 | (PIPE(display)->pipe_num<<24);
	PIPE(display)->plane = PLANE(display);
#ifndef CONFIG_MICRO
	plane_control |= (1<<30);
#endif

	/* Here the settings:
	 *   If line + pixel dbling, set 21,20 to 01b, and set Horz Multiply
	 *   If line dbling only,    set 21,20 to 11b
	 *   If pixel dbling only,   set 21,20 to 00b, but set Horz Multiply
	 *   If no doubling,         set 21,20 to 00b (no Horz Multiply)
	 * For pixel doubling
	 *           --> both progressive/interlaced modes
	 * For Line doubling
	 *           --> progressive modes only
	 */

	if (!(timing->mode_info_flags & IGD_SCAN_INTERLACE)) {
		/* Line doubling in progressive mode requires special bits */
		if (timing->mode_info_flags & IGD_LINE_DOUBLE) {
			/* BIT 20 for line & pixel doubling*/
			plane_control |= BIT20;
			/* check later, if no pixel doubling, set bit 21 too*/
		}
	}
	if (timing->mode_info_flags & IGD_PIXEL_DOUBLE) {
		/* Horz pixel multiply must be set for double */
		plane_control |= BIT11;
		/* TODO -> Plba can more than double,
		It can 3X, 4X etc. These arent exposed now */
	}
	else if(plane_control & BIT20){
		/* For line ONLY doubling, set bit 21 also '1' */
		plane_control |= BIT21;
	}

	mode_get_stride_stereo_plb(display, &stride, &stereo, 0);

	/* set color depth */
	switch (IGD_PF_DEPTH(fb_info->pixel_format)) {
	case PF_DEPTH_8:
		plane_control |= BIT27 | BIT30;
		break;
	case PF_DEPTH_16:
		plane_control |= BIT28 | BIT26;
		break;
	default:
	case PF_DEPTH_32:
		plane_control |= BIT28 | BIT27;
		break;
	}

	if(fb_info->flags & IGD_ENABLE_DISPLAY_GAMMA) {
		plane_control |= (BIT30);
	}

	EMGD_DEBUG(" Plane Control = 0x%lx", plane_control);
	EMGD_DEBUG(" Plane Base = 0x%lx", fb_info->visible_offset);
	EMGD_DEBUG(" Plane Pitch = 0x%lx", stride);
	EMGD_DEBUG(" Plane Size = 0x%lx", size);

	EMGD_WRITE32(stride, MMIO(display) + plane_reg + DSP_STRIDE_OFFSET);
	/*
	 * In reality this only exists for plane B. It doesn't seem to hurt
	 * plane A so just do it anyway and save us another case.
	 */
	EMGD_WRITE32(size, MMIO(display) + plane_reg + DSP_SIZE_OFFSET);

	/*EMGD_WRITE32(stereo, MMIO(display) + plane_reg + DSP_STEREO_OFFSET);
		- This register is Reserved ON plba */
	EMGD_WRITE32(fb_info->visible_offset,
		MMIO(display) + plane_reg + DSP_START_OFFSET);

	/* It seems we need push or trigger plane A/B to start to work
	 * on Poulsbo, especially for sDVO port. Let's write plane control
	 * register and start address register at last.
	 */
	EMGD_WRITE32(plane_control, MMIO(display) + plane_reg);
	EMGD_WRITE32(EMGD_READ32(MMIO(display) + start_addr_reg),
		MMIO(display) + start_addr_reg);

	igd_wait_vblank_plb((igd_display_h)display);

	EMGD_TRACE_EXIT;
	return;
}
//------------------------------------------------------------------
// Storm3D_Mesh_CollisionTable::ReBuild
//------------------------------------------------------------------
void Storm3D_Mesh_CollisionTable::ReBuild(Storm3D_Mesh *mesh)
{
	// TEMP!!!
	//return;

	int memory_before = 0; //frozenbyte::debug::Debug_MemoryManager::amountMemoryInUse();

	// Set owner
	owner=mesh;

	// Allocate memory for collision table
	delete tree;
	tree = 0;

	if(!owner->vertexes || !owner->faces[0])
		return;

	face_amount=owner->face_amount[0];

	if (owner->collision_faces != -1)
		face_amount = owner->collision_faces;

	SAFE_DELETE_ARRAY(faces);
	faces = new CollisionFace[face_amount];

	VC2 mmin(10000000.f, 10000000.f);
	VC2 mmax(-10000000.f, -10000000.f);

	// Create collision table
	for(int fi = 0; fi < face_amount; ++fi)
	{
		// Set vertexes
		faces[fi].vertex0=owner->vertexes[owner->faces[0][fi].vertex_index[0]].position;
		faces[fi].vertex1=owner->vertexes[owner->faces[0][fi].vertex_index[1]].position;
		faces[fi].vertex2=owner->vertexes[owner->faces[0][fi].vertex_index[2]].position;

		// Create edges
		faces[fi].e01=owner->vertexes[owner->faces[0][fi].vertex_index[1]].position-owner->vertexes[owner->faces[0][fi].vertex_index[0]].position;
		faces[fi].e02=owner->vertexes[owner->faces[0][fi].vertex_index[2]].position-owner->vertexes[owner->faces[0][fi].vertex_index[0]].position;
		VC3 e12=owner->vertexes[owner->faces[0][fi].vertex_index[2]].position-owner->vertexes[owner->faces[0][fi].vertex_index[1]].position;

		VC3 cross_e01_e02 = faces[fi].e01.GetCrossWith(faces[fi].e02);
		if(cross_e01_e02.GetSquareLength() < 0.0001f)
		{
			CollisionFace &face = faces[fi];
			face.sphere.radius = 0;

			continue;
		}

		// Create plane
		faces[fi].plane=PLANE(cross_e01_e02.GetNormalized(),faces[fi].vertex0);

		// psd
		CollisionFace *face = &faces[fi];
		face->sphere.position = (face->vertex0 + face->vertex1 + face->vertex2) / 3;
		
		face->sphere.radius = face->sphere.position.GetSquareRangeTo(face->vertex0);
		float tmp = face->sphere.position.GetSquareRangeTo(face->vertex1);
		if(tmp > face->sphere.radius)
			face->sphere.radius = tmp;
		tmp = face->sphere.position.GetSquareRangeTo(face->vertex2);
		if(tmp > face->sphere.radius)
			face->sphere.radius = tmp;

		face->sphere.radius = sqrtf(face->sphere.radius);

		if(face->sphere.position.x - face->sphere.radius < mmin.x)
			mmin.x = face->sphere.position.x - face->sphere.radius;
		if(face->sphere.position.z - face->sphere.radius < mmin.y)
			mmin.y = face->sphere.position.z - face->sphere.radius;

		if(face->sphere.position.x + face->sphere.radius > mmax.x)
			mmax.x = face->sphere.position.x + face->sphere.radius;
		if(face->sphere.position.z + face->sphere.radius > mmax.y)
			mmax.y = face->sphere.position.z + face->sphere.radius;
	}

	tree = new StaticQuadtree<CollisionFace>(mmin, mmax);
	//tree = new Quadtree<CollisionFace>(mmin, mmax);
	for(int i = 0; i < face_amount; ++i)
	{
		CollisionFace &face = faces[i];
		if(face.sphere.radius < 0.001f)
			continue;

		//tree->insert(&face, face.sphere.position, face.sphere.radius);

		float mmin = min(face.vertex0.y, face.vertex1.y);
		mmin = min(mmin, face.vertex2.y);
		float mmax = max(face.vertex0.y, face.vertex1.y);
		mmax = max(mmax, face.vertex2.y);

		tree->insert(face, face.sphere.position, face.sphere.radius, mmin, mmax);
	}
}
Esempio n. 4
0
/*!
 * Update internal data structures for the plane, pipe, and port as
 * requested. Allocate a new framebuffer if the new parameters do not
 * match the existing framebuffer.
 *
 * @param display
 * @param port_number
 * @param timing
 * @param pt_info User supplied timing info to check.
 * @param fb_info User supplied framebuffer info.
 * @param flags
 *
 * @return 0 on success
 * @return -IGD_ERROR_INVAL on failure
 */
static int mode_update_plane_pipe_ports(
	igd_display_context_t *display,
	unsigned short port_number,
	igd_timing_info_t *timing,
	igd_framebuffer_info_t *fb_info,
	igd_display_info_t *pt_info,
	unsigned long flags)
{
	int ret;
	int alloc_fb;
	unsigned long size = 0;
	igd_framebuffer_info_t *plane_fb_info;
	igd_display_plane_t *mirror;

	EMGD_TRACE_ENTER;

	EMGD_DEBUG("Port Number (%d)", port_number);

	EMGD_ASSERT( (fb_info || pt_info), "ERROR: fb_info & pt_info are NULL",
		-IGD_ERROR_INVAL);

	EMGD_ASSERT( PLANE(display)->fb_info, "ERROR: fb_info in plane is NULL",
		-IGD_ERROR_INVAL);

	plane_fb_info = PLANE(display)->fb_info;
	mirror = PLANE(display)->mirror;

	/*
	 * If there is a mirror plane (for Clone) and the mirror is populated
	 * then update our plane from the mirror. If the mirror is not populated
	 * then update the mirror from ours.
	 */
	if (mirror) {
		if(mirror->fb_info->flags) {
			OS_MEMCPY(plane_fb_info, mirror->fb_info,
				sizeof(igd_framebuffer_info_t));
		} else {
			OS_MEMCPY(mirror->fb_info, plane_fb_info,
				sizeof(igd_framebuffer_info_t));
		}
	}

	if (PORT(display, port_number)->pt_info == NULL) {
		if ((PORT(display, port_number)->pt_info = (igd_display_info_t *)
				OS_ALLOC(sizeof(igd_display_info_t))) == NULL) {
			EMGD_ERROR_EXIT("unable to alloc a pt_info struct in pipe.");
			return -IGD_ERROR_INVAL;
		}
	}

	/*
	 * If the fb_info was provided, and either we were asked to update
	 * the internal structures via the flags, or we are allocating a new
	 * framebuffer.
	 */
	if(fb_info && (flags & MODE_UPDATE_PLANE)) {

		/* Assume we will be allocating a FB */
		alloc_fb = 1;

		/* If the frambuffer parameters are unchanged then do not re-alloc */
		if((fb_info->width == plane_fb_info->width) &&
			(fb_info->height == plane_fb_info->height) &&
			(fb_info->pixel_format == plane_fb_info->pixel_format) &&
			(fb_info->flags == plane_fb_info->flags)) {
			alloc_fb = 0;
		}

		/* Do not re-alloc a framebuffer if the re-use flag is set. */
		if(fb_info->flags & IGD_REUSE_FB) {
			alloc_fb = 0;
			/* May need to get the MIN_PITCH flags */
			plane_fb_info->flags = (fb_info->flags & IGD_FB_FLAGS_MASK) |
				(plane_fb_info->flags & ~IGD_FB_FLAGS_MASK);
		}

		/*
		 * If we don't have a framebuffer at all then we MUST allocate
		 * one.
		 */
		if(!plane_fb_info->allocated && !fb_info->allocated) {
			alloc_fb = 1;
		}

		EMGD_DEBUG("plane_fb_info->fb_base_offset = 0x%08lx",
			plane_fb_info->fb_base_offset);
		if(alloc_fb) {
			if(plane_fb_info->allocated) {
				/* Free frame buffer memory */
				display->context->dispatch.gmm_free(
					plane_fb_info->fb_base_offset);
				plane_fb_info->allocated = 0;
			}

			fb_info->fb_base_offset = plane_fb_info->fb_base_offset;
			/*
			 * Keep the FB flags, add in Displayable flag and blank out
			 * the rest. This insures that any tiled or usage flags from an
			 * earlier call do not get reused.
			 */
			fb_info->flags = (fb_info->flags & IGD_FB_FLAGS_MASK) |
				IGD_SURFACE_DISPLAY;

			/*
			 * Framebuffer allocations must always come from a reservation
			 * if the IAL changes the address the new address must also be
			 * from a reservation.
			 */
			GMM_SET_DEBUG_NAME("Framebuffer");
			ret = display->context->dispatch.gmm_alloc_surface(
				&fb_info->fb_base_offset,
				fb_info->pixel_format,
				&fb_info->width,
				&fb_info->height,
				&fb_info->screen_pitch,
				&size,
				IGD_GMM_ALLOC_TYPE_RESERVATION,
				&fb_info->flags);
			if(ret) {
				EMGD_ERROR_EXIT("Allocation of Front buffer failed: %d", ret);
				return ret;
			}
			fb_info->allocated = 1;
			/* Set the visible offset to the newly-allocated offset: */
			fb_info->visible_offset = fb_info->fb_base_offset;
		} else {
			/* If not reallocating, use back the offset in plane_fb_info */
			fb_info->fb_base_offset = plane_fb_info->fb_base_offset;
		}

		OS_MEMCPY(plane_fb_info, fb_info, sizeof(igd_framebuffer_info_t));
		plane_fb_info->allocated = 1;
		EMGD_DEBUG("plane_fb_info->fb_base_offset = 0x%08lx",
			plane_fb_info->fb_base_offset);

	}

	if(timing && (flags & MODE_UPDATE_PIPE)) {
		EMGD_DEBUG("Updating pipe timing.");
		PIPE(display)->timing = timing;
		PIPE(display)->owner = display;
	}

	if(pt_info && (flags & MODE_UPDATE_PORT)) {
		EMGD_DEBUG("OLD_PT========NEW PT ");
		IGD_PRINTK_PTINFO_2(PORT(display, port_number)->pt_info, pt_info);
		OS_MEMCPY(PORT(display, port_number)->pt_info, pt_info,
				sizeof(igd_display_info_t));
	}

	EMGD_TRACE_EXIT;
	return 0;
} /* end mode_update_plane_pipe_ports() */
Esempio n. 5
0
/*!
 * Check user supplied timing against what is currently
 * programmed to see if it needs to change.  If the timing
 * isn't going to change, then we don't want to turn off and
 * reprogram the port.
 *
 * NOTE: If this increases the size too much for vbios, then it
 * could be ifndef CONFIG_MICRO with an else that returns 1. That
 * would mean vbios wouldn't have these checks and always assume
 * the timing was changing.
 *
 * @param display
 * @param new_dc DC changes always require port/plane/pipe programming.
 * @param pt_info User supplied timing info to check.
 * @param fb_info User supplied framebuffer info.
 * @param port_number
 * @param display_mask Which display is being checked.
 * @param alter flags used to force the alter
 *
 * @return 1 timing has changed
 * @return 0 timing hasn't changed
 */
static int timing_changed(igd_display_context_t *display,
		unsigned long new_dc,
		unsigned long dc,
		igd_display_info_t *pt_info,
		igd_framebuffer_info_t *fb_info,
		unsigned long display_mask,
		unsigned long flags)
{
	igd_framebuffer_info_t *cfb;

	EMGD_TRACE_ENTER;

	/*
	 * will this cover every case?  Can a change on one display effect
	 * the timings of the other?  I don't think so.
	 */
	if ((new_dc & display_mask) != (dc & display_mask)) {
		return 1; /* Ports are changing on this display, must re-program. */
	}

	/*
	 * Make sure the owner port has a pt_info, if not then we'll assume
	 * that it hasn't been programmed yet and thus the timings are going
	 * to change.
	 */
	if (PORT_OWNER(display)->pt_info == NULL) {
		return 1;
	}

	/*
	 * Make sure we have valid timing info.  If not, then don't try
	 * and change the timings.
	 */
	if (!pt_info || !fb_info) {
		return 0;
	}

	/*
	 * If the caller really wants to re-program the planes/pipes/ports
	 * then do it
	 */

	if (flags & IGD_FORCE_ALTER) {
		return 1;
	}

	/*
	 * Check only width, height, refresh. If these don't match, then we
	 * know that something is changing.
	 */

	if ((pt_info->width == PORT_OWNER(display)->pt_info->width) &&
			(pt_info->height == PORT_OWNER(display)->pt_info->height) &&
			(pt_info->refresh == PORT_OWNER(display)->pt_info->refresh)) {

		/* Check framebuffer for changes, fb changes may change timing */
		if ((cfb = PLANE(display)->fb_info) != NULL) {
			if ((cfb->width != fb_info->width) ||
				(cfb->height != fb_info->height) ||
				(cfb->pixel_format != fb_info->pixel_format) ||
				(cfb->flags != fb_info->flags)) {
				/* Timing ok buf fb_info doesn't match */
				return 1;
			}
		}
	} else {
		/* Timing doesn't match */
		return 1;
	}

	/* Timing and fb have not changed */
	EMGD_TRACE_EXIT;
	return 0;
}
Esempio n. 6
0
/*!
 * This function sets up planes, pipes, and ports
 * with the configuration passed in and returnes either one
 * or two display handle lists.
 *
 * @param driver_handle from igd_init_driver().
 * @param primary on return, this points to a list of displays.
 * @param primary_ptinfo incoming timing info for the primary.
 * @param primary_fbinfo incoming framebuffer info.
 * @param secondary on return, this points to a list of displays.
 * @param secondary_fbinfo incoming framebuffer info.
 * @param dc display configuration
 * @param flags modify function behavior
 *
 * @return 0 on success
 * @return -IGD_INVAL on failure
 */
int igd_alter_displays(
	igd_driver_h driver_handle,
	igd_display_h *_primary,
	igd_display_info_t *primary_pt_info,
	igd_framebuffer_info_t *primary_fb_info,
	igd_display_h *_secondary,
	igd_display_info_t *secondary_pt_info,
	igd_framebuffer_info_t *secondary_fb_info,
	unsigned long dc,
	unsigned long flags)
{
	igd_context_t *context = (igd_context_t *)driver_handle;
	igd_display_context_t **primary = (igd_display_context_t **)_primary;
	igd_display_context_t **secondary = (igd_display_context_t **)_secondary;
	igd_framebuffer_info_t *fb_info = NULL;
	igd_display_context_t *display = NULL,*tv_display=NULL;
	int p;
	int ret;
	unsigned short tv_port_num=0;
	int p_chng = 1, s_chng = 1;
	unsigned char disable_plane_pipe = 0;
	unsigned long current_dc;

#if 0 /* Ian Elliott is taking this out ... see comment below */
#ifndef CONFIG_MICRO
	igd_framebuffer_info_t *plane_fb_info = NULL;
#endif
#endif /* 0 -- Ian is taking this out */

	EMGD_TRACE_ENTER;

	/*
	 * Make sure the DC is valid
	 *
	 * vBIOS won't be able to do this every time, for now only have
	 * the drivers's do the check.
	 */
#ifndef CONFIG_MICRO
	if (dc && !dsp_valid_dc(dc, 0)) {
		EMGD_ERROR_EXIT("Invalid display configuration: 0x%08lx", dc);
		return -IGD_ERROR_INVAL;
	}
#endif


	/*
	 * Can all display_info's and fb_info's be NULL?  I.E. make this
	 * function do an alloc of display handles only?  If so, then
	 * check for that condition and return without error. Otherwise
	 * return an error.
	 */
	if (dc && (!primary_pt_info && !primary_fb_info) &&
			(!secondary_pt_info && !secondary_fb_info)) {
		EMGD_ERROR_EXIT("Invalid timing and framebuffer info");
		return -IGD_ERROR_INVAL;
	}

#ifndef CONFIG_MICRO
	/* FIXME: GDK Change this to dispatch->idle() */
	if (dsp_wait_rb(mode_context->context) != 0) {
		return -IGD_ERROR_INVAL;
	}
#endif

	/* If seamless request is NOT set , then do reset_plane_pipe_ports
	 * else delay it until we cannot support it.
	 * If seamless is requested by the user and we CAN support it
	 * then we need to make sure reset_plane_pipe_ports is NOT
	 * called. That's the whole point anyway. Not to reset anything
	 * during seamless transition
	 */
	if(mode_context->seamless != TRUE) {

		/* Reset planes/pipes/ports before doing first alter display */
		if (mode_context->first_alter) {
			mode_context->dispatch->reset_plane_pipe_ports(
									mode_context->context);
			mode_context->first_alter = FALSE;
		}
	}

	current_dc = *(context->mod_dispatch.dsp_current_dc);

#ifndef CONFIG_MICRO
	/* Check if platform needs force alter
	* 	to make sure we run tuning code. This
	* 	is for TNC-B0 workaround.*/
	if (mode_context->dispatch->dsp_is_force_alter_required){
		if (mode_context->dispatch-> dsp_is_force_alter_required(context->
						mod_dispatch.dsp_display_list[IGD_DC_PRIMARY(current_dc)],
						current_dc, dc)){
				flags |= IGD_FORCE_ALTER;
		}
	}
#endif

	/*
	 * Turn off the planes, pipes, and ports associated with the current
	 * DC. However, limit the change to the primary if the secondary
	 * display handle is NULL or limit the change to the secondary if the
	 * the pimary display handle is NULL.
	 */
	for (p = 7; p > 0; p--) {
		if (p > 4) {
			display = NULL;
			if (DC_PORT_NUMBER(current_dc, p)) {
				display = context->mod_dispatch.
					dsp_display_list[IGD_DC_SECONDARY(current_dc)];
				s_chng = TIMING_CHANGED(display, dc, current_dc,
						secondary_pt_info, secondary_fb_info,
						(unsigned long)0xfff00000, flags);
			}

			if (s_chng && display && secondary) {
		/* if the port is TV, then don't set the power to S3 as this causes
		 * blank screen and system hang on LVDS on FSDOS, probably because the
		 * external clock needs to be on till the pipes and
		 * DPLLs are off
		 */
				if(PORT(display,DC_PORT_NUMBER(current_dc, p))->pd_type ==
					PD_DISPLAY_TVOUT) {
					tv_display = display;
					tv_port_num = DC_PORT_NUMBER(current_dc, p);
				} else {
					ret = mode_context->dispatch->program_port(display,
					      DC_PORT_NUMBER(current_dc, p), FALSE);
				}
				/* The secondary pipe master */
				if (p == 5) {
					disable_plane_pipe = 1;
				}
			}
		} else {
			display = NULL;
			if (DC_PORT_NUMBER(current_dc, p)) {
				display = context->mod_dispatch.
					dsp_display_list[IGD_DC_PRIMARY(current_dc)];
				p_chng = TIMING_CHANGED(display, dc, current_dc,
						primary_pt_info, primary_fb_info,
						(unsigned long)0x000ffff0, flags);
			}

			if (p_chng && display && primary) {
		/* if the port is TV, then don't set the power to S3 as this causes
		 * blank screen and system hang on LVDS on FSDOS, probably because the
		 * external clock needs to be on till the pipes and
		 * DPLLs are off
		 */
				if(PORT(display,DC_PORT_NUMBER(current_dc, p))->pd_type ==
					PD_DISPLAY_TVOUT) {
					tv_display = display;
					tv_port_num = DC_PORT_NUMBER(current_dc, p);
				} else {
					ret = mode_context->dispatch->program_port(display,
				      DC_PORT_NUMBER(current_dc, p), FALSE);
				}
				/* The primary pipe master */
				if (p == 1) {
					disable_plane_pipe = 1;
				}
			}
		}

		/* Disable plane and pipe after disabling the ports */
		if (disable_plane_pipe) {
			if(mode_context->dispatch->full) {
				mode_context->dispatch->full->program_cursor(display, FALSE);
			}
			mode_context->dispatch->program_plane(display, FALSE);
			mode_context->dispatch->program_pipe(display, FALSE);
			/*pipes and dplls are off, now turn off tv port */
			if(tv_display) {
				ret = mode_context->dispatch->program_port(tv_display,
					tv_port_num, FALSE);
				tv_display = NULL;
			}
			disable_plane_pipe = 0;
		}
	}

#ifndef CONFIG_MICRO
	/* If DC is zero, then return here. A zero dc turns everything off */
	/* This never happens for VBIOS since it only always calls *
	 * alter_displays at the same point with the same valid DC */
	if (!dc) {
		int i;
		mode_context->dispatch->reset_plane_pipe_ports(mode_context->context);
		/* Should de-allocate everything here */
		dsp_alloc(driver_handle, dc, flags);
		/*
		 * FIXME: This should be done inside dsp alloc, mode module does
		 * not own this information.
		 * When dc = 0, set all displays allocated to 0.
		 */
		for (i=0; i<IGD_MAX_PORTS+1; i++) {
			if (context->mod_dispatch.dsp_display_list[i]) {
				context->mod_dispatch.dsp_display_list[i]->allocated = 0;
			}
			context->mod_dispatch.dsp_display_list[i] = NULL;
		}

		return 0;
	}
#endif

	/*
	 * Check the DC (display configuration). If it is the same as the
	 * current configuration, then don't change any allocations, only
	 * modify the framebuffers and timings.
	 */
	if (dc != current_dc) {
		EMGD_DEBUG("Allocate display handles based on DC");

#ifndef CONFIG_MICRO
		if (swap_required(current_dc, dc, primary)) {
			swap_fb_cursor();
		}
#endif
		/*
		 * This function should never be called after VBIOS initialization *
		 * The dsp_alloc is discarded after VBIOS init and is over-  *
		 * written by font tables. Thus in VBIOS IAL, alter_displays *
		 * is never get called with a different DC from the 1st time *
		 */
		dsp_alloc(driver_handle, dc, flags);

	}

	/* Attach the displays to the caller's pointers */
	if (primary) {
		*primary = context->mod_dispatch.dsp_display_list[IGD_DC_PRIMARY(dc)];
#ifndef CONFIG_MICRO
		if (*primary && context->mod_dispatch.alloc_queues) {
			ret = context->mod_dispatch.alloc_queues(driver_handle,
				(*primary)->pipe, flags);
			if (ret) {
				EMGD_ERROR("unable to allocate command queues");
			}
		}
#endif
	}
	if (secondary) {
		EMGD_DEBUG("Attaching display 1 to secondary pointer");
		*secondary = context->mod_dispatch.
			dsp_display_list[IGD_DC_SECONDARY(dc)];
#ifndef CONFIG_MICRO
		if (*secondary && context->mod_dispatch.alloc_queues) {
			ret = context->mod_dispatch.alloc_queues(driver_handle,
				(*secondary)->pipe, flags);
			if (ret) {
				EMGD_ERROR("unable to allocate command queues");
			}
		}
#endif
	}

	/*
	 * Configure the primary display. This configures the timings and the
	 * framebuffer. Once configured, it turns everythying on.
	 */
	if(primary && *primary && (primary_pt_info || primary_fb_info) && p_chng) {
		EMGD_DEBUG("Configure primary timings");
		/* make framebuffer changes */
		if (primary_fb_info) {
			/* set up new frame buffer info */
			fb_info = primary_fb_info;
		} else {
			fb_info = PLANE(*primary)->fb_info;
		}

		ret = configure_display(driver_handle,
				(igd_display_context_t *)(*primary), primary_pt_info,
				fb_info, dc, 0, 4, flags);
		if (ret) {
			EMGD_DEBUG("Primary display disabled.");
		}
	}

	/*
	 * Configure the secondary display. This configures the timings and the
	 * framebuffer. Once configured, it turns everythying on.
	 *
	 * How close is this code to the code for the primary?  Could this
	 * be moved to a separate function?
	 */
	if (secondary != NULL) {

#ifndef CONFIG_MICRO
		/*
		 * In the case where we are in extended or clone and our pipe is not
		 * turned on, we need to turn the pipes on.
		 * We can run into this situation on pre-Cantiga Gen platforms on Linux
		 * where LVDS was the primary display and was assigned PIPE B. Then we
		 * are switching from LVDS to another display and that other display
		 * wants to take PIPE A. In this case PIPE B will be turned on, the
		 * display's new port will take PIPE A and turn on PIPE A.  The second
		 * display thinks it is still PIPE A and nothing has changed for it.
		 * In this case where our pipe is not turned on, we need to let the
		 * system know that something has changed.
		 */
		if ((IGD_DC_CLONE(dc) || IGD_DC_EXTENDED(dc))
			&& !(EMGD_READ32(MMIO(*secondary) + PIPE(*secondary)->pipe_reg)
			& 0x80000000)) {
			s_chng = 1;
		}
#endif

		EMGD_DEBUG("Starting secondary pipe programming");
		if ((*secondary != NULL) && (secondary_pt_info || secondary_fb_info) &&
				s_chng){
			/*
			 * Configure the framebuffer.  For clone, it is the same
			 * as the primary. For DIH, it is a unique fb.
			 */
			EMGD_DEBUG("configure secondary framebuffer");
			if (dc & IGD_DISPLAY_CONFIG_CLONE) {
				fb_info = PLANE(*primary)->fb_info;
			} else {
				if (secondary_fb_info) {
					fb_info = secondary_fb_info;
				} else {
					fb_info = PLANE(*secondary)->fb_info;
				}
			}

			ret = configure_display(driver_handle,
					(igd_display_context_t *)(*secondary), secondary_pt_info,
					fb_info, dc, 4, 7, flags);
			if (ret) {
				EMGD_DEBUG("Secondary display disabled.");
				EMGD_ERROR("Secondary display disabled.");
			}
		}
	} else {
		EMGD_DEBUG("Skipped secondary programming, NULL handle");
	}

	/*
	 * Workaround: wait for Vblank to avoid people accessing display
	 * plane registers before the register is updated properly.
	 */
	if (primary && *primary) {
		EMGD_DEBUG("Wait for vblank on primary display (%p)", primary);
		EMGD_DEBUG("Wait for vblank on primary display (%p)", *primary);
		mode_context->dispatch->wait_vblank(*primary);
	} else if (secondary && *secondary) {
		EMGD_DEBUG("Wait for vblank on secondary display");
		mode_context->dispatch->wait_vblank(*secondary);
	}

	EMGD_TRACE_EXIT;
	return 0;
}
Esempio n. 7
0
unsigned int ovl2_send_instr_tnc(
	igd_display_context_t     *display,
	ovl2_reg_tnc_t    *spritec_regs_tnc,
	unsigned int      flags)
{
	unsigned char *mmio = MMIO(display);
	 unsigned long tmp, pipe_reg, pipe_num;
	inter_module_dispatch_t *md;
	platform_context_tnc_t * platform;


	EMGD_TRACE_ENTER;

	/* We dont need the CMD_WAIT_OVL2_TNC instruction coz
	 * our alter_ovl code already querried status
	 * for last flip completion before getting here. See
	 * micro_prepare_ovl2_tnc called by alter_ovl2_tnc.
	 * It calls query overlay before the next flip
	 */

	/*If Overlay+FB Blend is requested and the FB is xRGB
	 *turn on the ARGB format. */
	if(ovl_context->fb_blend_ovl) {
		if((flags & IGD_OVL_ALTER_ON) == IGD_OVL_ALTER_ON) {
			tmp = EMGD_READ32(mmio + PLANE(display)->plane_reg);
			if((tmp & 0x3c000000) == 0x18000000) {
				tmp = tmp & 0xc3FFFFFF;
				EMGD_WRITE32(tmp | 0x1c000000, mmio + PLANE(display)->plane_reg);
				EMGD_READ32(mmio + PLANE(display)->plane_reg);
				tmp = EMGD_READ32(mmio + PLANE(display)->plane_reg + 0x1c);
				EMGD_WRITE32(tmp, mmio + PLANE(display)->plane_reg + 0x1c);
			}
		} else {
			tmp =  EMGD_READ32(mmio + PLANE(display)->plane_reg);
			if((tmp & 0x3c000000) == 0x1c000000) {
				tmp = tmp & 0xc3FFFFFF;
				EMGD_WRITE32(tmp | 0x18000000, mmio + PLANE(display)->plane_reg);
				EMGD_READ32(mmio + PLANE(display)->plane_reg);
				tmp = EMGD_READ32(mmio + PLANE(display)->plane_reg + 0x1c);
				EMGD_WRITE32(tmp, mmio + PLANE(display)->plane_reg + 0x1c);
				OS_SLEEP(100);
			}
		}
	}

	/* Send a load register instruction to write the Plane C sprite address
	 * which is the trigger register.
	 * This is an instruction, so it happens after blend, and since it
	 * is an instruction, we do not have to poll waiting for it. */
	EMGD_WRITE32(spritec_regs_tnc->start, mmio + 0x7219C);

	/* Since the ISR bit 0x100 actually doesnt work,
	 * we need to setup a trigger for a VBLANK event
	 * on Pipe-B to guarantee that the Sprite-C had
	 * actually completed its last flip.
	 * (ISR bit was tested on Poulsbo D2 by capturing
	 * timestamps of quick successive alter_overlays..
	 * checked ISR bit directly after the write to Sprite
	 * C Address register in process_vqueue handling..
	 * the ISR bit never changed
	 */

	md = &display->context->mod_dispatch;
	platform = (platform_context_tnc_t *)display->context->
					platform_context;

	pipe_num = PIPE(display)->pipe_num; 
    
	if(pipe_num){ 
		pipe_reg = PIPEB_STAT; 
	} else { 
		pipe_reg = PIPEA_STAT; 
	} 

	if(md && md->set_flip_pending){
		OS_PTHREAD_MUTEX_LOCK(&platform->flip_mutex);
		md->set_flip_pending(MMIO(display), pipe_reg);
		OS_PTHREAD_MUTEX_UNLOCK(&platform->flip_mutex);
	}

	ovl_context->sync2 = WAIT_FOR_FLIP;

	EMGD_TRACE_EXIT;
	return IGD_SUCCESS;
}
Esempio n. 8
0
unsigned int ovl2_send_instr_plb(
	igd_display_context_t     *display,
	ovl2_reg_plb_t    *spritec_regs_plb,
	unsigned int      flags)
{
	unsigned char * mmio = MMIO(display);
	unsigned long tmp;
	inter_module_dispatch_t *md;
	platform_context_plb_t * platform;
	unsigned int pipe_num;
	unsigned long pipe_reg;
	int ret;

	EMGD_TRACE_ENTER;

	/* We dont need the CMD_WAIT_OVL2_PLB instruction coz
	 * our alter_ovl code already querried status
	 * for last flip completion before getting here. See
	 * micro_prepare_ovl2_plb called by alter_ovl2_plb.
	 * It calls query overlay before the next flip
	 */


	/*
	 * If Overlay + FB Blend is requested and the FB is xRGB
	 * turn on the ARGB format.
	 */
	if(ovl_context->fb_blend_ovl) {
		if ((flags & IGD_OVL_ALTER_ON) != IGD_OVL_ALTER_ON) {
			tmp = EMGD_READ32(mmio +  PLANE(display)->plane_reg);
			if((tmp & 0x3c000000) == 0x1c000000) {
				tmp = tmp & 0xc3FFFFFF;
				EMGD_WRITE32(tmp | 0x18000000, mmio +  PLANE(display)->plane_reg);
				tmp = EMGD_READ32(mmio + PLANE(display)->plane_reg + 4);
				EMGD_WRITE32(tmp, mmio + PLANE(display)->plane_reg + 4);
				OS_SLEEP(100);
			}
		} else {
			tmp = EMGD_READ32(mmio +  PLANE(display)->plane_reg);
			if((tmp & 0x3c000000) == 0x18000000) {
				EMGD_WRITE32(tmp | 0x1c000000, mmio +  PLANE(display)->plane_reg);
				tmp = EMGD_READ32(mmio + PLANE(display)->plane_reg + 4);
				EMGD_WRITE32(tmp, mmio + PLANE(display)->plane_reg + 4);
			}
		}
	}


	/* Send a load register instruction to write the Plane C sprite address
	 * which is the trigger register.
	 * This is an instruction, so it happens after blend, and since it
	 * is an instruction, we do not have to poll waiting for it. */
	EMGD_WRITE32(spritec_regs_plb->start, mmio + 0x72184);

	md = &display->context->mod_dispatch;
	platform = (platform_context_plb_t *)display->context->
			platform_context;

	pipe_num = PIPE(display)->pipe_num;

	if(pipe_num){
		pipe_reg = 0x71024;
	} else {
		pipe_reg = 0x70024;
	}

        if(md && md->set_flip_pending){
                /* For second overlay, Poulsbo has no ISR bit
	         * to reflect the flip pending for Display
                 * Sprite C. So we use Pipe-B vblank status
                 * as a substitute
                 */
                ret = OS_PTHREAD_MUTEX_LOCK(&platform->flip_mutex);
                md->set_flip_pending(MMIO(display), pipe_reg);
                OS_PTHREAD_MUTEX_UNLOCK(&platform->flip_mutex);
        }

	ovl_context->sync2 = 0;

	display->context->dispatch.sync(display,
		IGD_PRIORITY_NORMAL,
		&ovl_context->sync2,
		IGD_SYNC_NONBLOCK);

	EMGD_TRACE_EXIT;
	return IGD_SUCCESS;
}