Ejemplo n.º 1
0
/*!
 * This function programs the Timing registers and clock registers and
 * other control registers for PIPE.
 *
 * @param display
 * @param status
 *
 * @return void
 */
static void program_pipe_plb(igd_display_context_t *display,
	unsigned long status)
{
	unsigned long   timing_reg;
	unsigned long   pipe_conf;
	unsigned long   hactive, vactive;
	igd_timing_info_t  *pTimings;
	unsigned long temp;
#ifndef CONFIG_MICRO
	igd_display_port_t *port;
	int i;
#endif

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

	pipe_conf = device_data->pipe_preserve &
		EMGD_READ32(MMIO(display) + PIPE(display)->pipe_reg);

	/* Reset the plane of this pipe back to NULL, it will be set on the
	 * call to program_plane, which is ok, since program_pipe occurs
	 * before program_plane */
	PIPE(display)->plane = NULL;

	if((status == FALSE) ||
		(GET_DEVICE_POWER_STATE(display) == IGD_POWERSTATE_D3)) {
		/* Disable pipe */
		EMGD_WRITE32(pipe_conf & (~0x80000000),
			MMIO(display) + PIPE(display)->pipe_reg);

		return;
	}

	pTimings = PIPE(display)->timing;

	/*
	 * If the mode is VGA and the PD says it handles all VGA modes without
	 * reprogramming then just set the mode and leave centering off.
	 */
	if(pTimings->mode_info_flags & IGD_MODE_VESA) {
		if (pTimings->mode_number <= VGA_MODE_NUM_MAX) {
			/* Pipe timings and clocks are not used but it must be on anyway */
			EMGD_WRITE32(pipe_conf | 0x80000000,
				MMIO(display) + PIPE(display)->pipe_reg);
			program_pipe_vga_plb(display);
			return;
		} else {
#ifdef CONFIG_MICRO
			set_256_palette(MMIO(display));
#endif
		}
	}

	/* Program dot clock divisors. */
	program_clock_plb(display, PIPE(display)->clock_reg, pTimings->dclk);

	/* Program timing registers for the pipe */
	timing_reg = PIPE(display)->timing_reg;
	if (pTimings->mode_info_flags & IGD_PIXEL_DOUBLE) {
		hactive = (unsigned long)pTimings->width*2 - 1;
	} else {
		hactive = (unsigned long)pTimings->width - 1;
	}

	if (pTimings->mode_info_flags & IGD_LINE_DOUBLE) {
		if (pTimings->mode_info_flags & IGD_SCAN_INTERLACE) {
			vactive = (unsigned long)pTimings->height - 1;
		} else {
			vactive = (unsigned long)pTimings->height*2 - 1;
		}
	} else {
		if (pTimings->mode_info_flags & IGD_SCAN_INTERLACE) {
			vactive = (unsigned long)pTimings->height/2 - 1;
		} else {
			vactive = (unsigned long)pTimings->height - 1;
		}
	}

	/*
	 * DPLL should be on at this point which is required for touching
	 * the palette.
	 */
#ifndef CONFIG_MICRO
	/* reset the palette */
	for (i = 0; i < 256; i++) {
		EMGD_WRITE32(((i<<16) | (i<<8) | i),
			MMIO(display) + PIPE(display)->palette_reg + i*4);
	}

	/* apply color correction */
	port = PORT_OWNER(display);
	for( i = 0; PD_ATTR_LIST_END != port->attributes[i].id; i++ ) {

		if ((PD_ATTR_ID_FB_GAMMA      == (port->attributes[i].id)) ||
			(PD_ATTR_ID_FB_BRIGHTNESS == (port->attributes[i].id)) ||
			(PD_ATTR_ID_FB_BRIGHTNESS == (port->attributes[i].id)))  {

			mode_context->dispatch->full->set_color_correct(display);
		}
	}
#endif

	/*
	 * NOTE: For size reasons the timng table contains unsigned short
	 * values. Don't shift them past 16. Use a temp instead.
	 * All register offsets and bit shift are verified for Napa
	 */
	temp = ((unsigned long)pTimings->htotal << 16) | hactive;
	EMGD_WRITE32(temp, MMIO(display) + timing_reg);

	temp = ((unsigned long)pTimings->hblank_end << 16) |
		(unsigned long)pTimings->hblank_start;
	EMGD_WRITE32(temp, MMIO(display) + timing_reg + 0x04);

	temp = ((unsigned long)pTimings->hsync_end << 16) |
		(unsigned long)pTimings->hsync_start;
	EMGD_WRITE32(temp, MMIO(display) + timing_reg + 0x08);

	temp = ((unsigned long)pTimings->vtotal << 16) | vactive;
	EMGD_WRITE32(temp, MMIO(display) + timing_reg + 0x0C);

	temp = ((unsigned long)pTimings->vblank_end << 16) |
		(unsigned long)pTimings->vblank_start;
	EMGD_WRITE32(temp, MMIO(display) + timing_reg + 0x10);

	temp = ((unsigned long)pTimings->vsync_end << 16) |
		(unsigned long)pTimings->vsync_start;
	EMGD_WRITE32(temp, MMIO(display) + timing_reg + 0x14);

	/*
	 * If there is a linked mode it is either the VGA or a scaled
	 * mode. If it is scaled then we need to use it as the source size.
	 */
	if(pTimings->extn_ptr) {
		igd_timing_info_t *scaled_timings =
			(igd_timing_info_t *)pTimings->extn_ptr;
		if((scaled_timings->mode_info_flags & IGD_MODE_VESA) &&
			(scaled_timings->mode_number <= VGA_MODE_NUM_MAX)) {
			temp = (hactive << 16) | vactive;
		} else {
			temp = (unsigned long)scaled_timings->width  - 1;
			temp = (temp << 16) |
				(unsigned long)(scaled_timings->height - 1);
		}
	} else {
		temp = (hactive << 16) | vactive;
	}
	EMGD_WRITE32(temp, MMIO(display) + timing_reg + 0x1C);

	/* Set other registers */

	/*
	 * FIXME: max_dclk needs to be determined from core clock
	 * at init time. 915 etc has several skus with different
	 * clocks for the same device ID.
	 *
	 */

	/* These values are derived from the Poulsbo B-Spec as
	 * the suggested values */
	WRITE_MMIO_REG (display, FW_BLC1, device_data->fw_blc1);
	WRITE_MMIO_REG (display, FW_BLC2, device_data->fw_blc2);
	WRITE_MMIO_REG (display, FW_BLC3, device_data->fw_blc3);
	WRITE_MMIO_REG (display, FW_BLC_SELF, device_data->fw_self);
	WRITE_MMIO_REG (display, DSP_ARB, device_data->dsp_arb);

	/* The SGX 2D engine can saturate the memory bus and starve
	 * the display engine causing visible screen tearing.
	 * This reduces the priority of the SGX vs. display engine
	 */
	temp = READ_MMIO_REG (display, G_DEBUG);
	WRITE_MMIO_REG (display, G_DEBUG, (temp | (1 << 11)));

	pipe_conf |= PIPE_ENABLE;
	WRITE_MMIO_REG(display, PIPE(display)->pipe_reg, pipe_conf);

	/*
	 * Set the VGA address range to 0xa0000 so that a normal (not VGA)
	 * mode can be accessed through 0xa0000 in a 16bit world.
	 */
	WRITE_AR(MMIO(display), 0x10, 0xb);
	WRITE_VGA(MMIO(display), GR_PORT, 0x06, 0x5);
	WRITE_VGA(MMIO(display), GR_PORT, 0x10, 0x1);

	if(pTimings->extn_ptr) {
		/* This means either internal scaling (LVDS) or centered VGA */
		pTimings = pTimings->extn_ptr;
		if(pTimings->extn_ptr) {
			/* This is both the scaled and centered VGA */
			pTimings = pTimings->extn_ptr;
		}
		if(pTimings->mode_info_flags & IGD_MODE_VESA) {
			if (pTimings->mode_number <= VGA_MODE_NUM_MAX) {
				program_pipe_vga_plb(display);
			} else {
#ifdef CONFIG_MICRO
				set_256_palette(MMIO(display));
#endif
			}
		}
	}

	EMGD_TRACE_EXIT;
	return;
}
Ejemplo n.º 2
0
/*!
 * Restore the VGA Register state from the specifed state buffer.
 *
 * @param context the current device context
 * @param vga_buffer this is where the VGA register state is saved
 * @param ar_regs AR registers to save
 * @param cr_regs CR registers to save
 * @param sr_regs SR registers to save
 * @param gr_regs GR registers to save
 *
 * @return 0
 */
static int reg_restore_vga_plb(
	igd_context_t *context,
	vga_state_plb_t *vga_buffer,
	unsigned char *ar_regs,
	unsigned char *cr_regs,
	unsigned char *sr_regs,
	unsigned char *gr_regs)
{
	unsigned long i;
	unsigned char *mmio;
	unsigned long bit_mask;
	mmio = context->device_context.virt_mmadr;

	/* Restore the plane latches.
	 *
	 * BP: I don't understand what this block is doing and it doesn't
	 * seem necessary. Should check this against the spec and figure
	 * out what it really does.
	 */

	/* Memory Mode Register */
	WRITE_VGA(mmio, SR_PORT, SR04, 0x06);
	/* GR05, Graphics Mode Register */
	WRITE_VGA(mmio, GR_PORT, GR05, 0x00);
	/* GR06, Micsellaneous Register */
	WRITE_VGA(mmio, GR_PORT, GR06, 0x05);
	/* GR08, Bit Mask Register */
	WRITE_VGA(mmio, GR_PORT, GR08, 0xFF);

	for (i=0, bit_mask=1; i<PLANE_LATCH_COUNT; i++, bit_mask<<= 1)  {
		/* Set plane select register */
		WRITE_VGA(mmio, GR_PORT, GR04, i);
		/* Plane/Map mask register */
		WRITE_VGA(mmio, SR_PORT, SR02, bit_mask);
	}

	for (i=0, bit_mask=1; i<PLANE_LATCH_COUNT; i++, bit_mask<<= 1)  {
		/* Plane/Map mask register again?? */
		WRITE_VGA(mmio, SR_PORT, SR02, bit_mask);
	}

	/* Restore standard VGA registers.
	 * 2) Sequence registers
	 * 1) MSR register
	 * 3) CRTC registers
	 * 4) Graphics registers
	 * 5) Attribute registers
	 * 6) VGA Feature register
	 * 7) Index restisters
	 */


	WRITE_VGA(mmio, SR_PORT, SR00, 01); /* Do sync reset */

	for (i=0; sr_regs[i] != 0xff; i++) {
		WRITE_VGA(mmio, SR_PORT, sr_regs[i], vga_buffer->sr[i]);
	}


	EMGD_WRITE8(vga_buffer->msr, mmio + MSR_PORT);
	WRITE_VGA(mmio, SR_PORT, SR00, 0x03); /* Set to normal operation */

	/* Unlock CRTC */
	WRITE_VGA(mmio, CR_PORT, CR11, vga_buffer->cr[0x11] & 0x7F);
	for (i=0; cr_regs[i] != 0xff; i++) {
		WRITE_VGA(mmio, CR_PORT, cr_regs[i], vga_buffer->cr[i]);
	}

	for (i=0; gr_regs[i] != 0xff; i++) {
		WRITE_VGA(mmio, GR_PORT, gr_regs[i], vga_buffer->gr[i]);
	}

	for (i=0; ar_regs[i] != 0xff; i++) {
		WRITE_AR(mmio, ar_regs[i], vga_buffer->ar[i]);
	}

	EMGD_WRITE8(vga_buffer->fcr, mmio + FEATURE_CONT_REG);

	/* Restore index registers. Is this necessary?  */
	EMGD_WRITE8(vga_buffer->sr_index, mmio + SR_PORT);
	EMGD_WRITE8(vga_buffer->cr_index, mmio + CR_PORT);
	EMGD_WRITE8(vga_buffer->gr_index, mmio + GR_PORT);

	/* Lock CRTC */
	WRITE_VGA(mmio, CR_PORT, CR11, vga_buffer->cr[0x11] | 0x80);

	return 0;
}