Kernel  |  4.4

下载     查看原文件
C++程序  |  203行  |  7.22 KB

#include "ddk750_help.h"
#include "ddk750_reg.h"
#include "ddk750_mode.h"
#include "ddk750_chip.h"

/*
	SM750LE only:
    This function takes care extra registers and bit fields required to set
    up a mode in SM750LE

	Explanation about Display Control register:
    HW only supports 7 predefined pixel clocks, and clock select is
    in bit 29:27 of	Display Control register.
*/
static unsigned long displayControlAdjust_SM750LE(mode_parameter_t *pModeParam, unsigned long dispControl)
{
	unsigned long x, y;

	x = pModeParam->horizontal_display_end;
	y = pModeParam->vertical_display_end;

	/* SM750LE has to set up the top-left and bottom-right
	   registers as well.
	   Note that normal SM750/SM718 only use those two register for
	   auto-centering mode.
	 */
	POKE32(CRT_AUTO_CENTERING_TL,
	FIELD_VALUE(0, CRT_AUTO_CENTERING_TL, TOP, 0)
	| FIELD_VALUE(0, CRT_AUTO_CENTERING_TL, LEFT, 0));

	POKE32(CRT_AUTO_CENTERING_BR,
	FIELD_VALUE(0, CRT_AUTO_CENTERING_BR, BOTTOM, y-1)
	| FIELD_VALUE(0, CRT_AUTO_CENTERING_BR, RIGHT, x-1));

	/* Assume common fields in dispControl have been properly set before
	   calling this function.
	   This function only sets the extra fields in dispControl.
	 */

	/* Clear bit 29:27 of display control register */
	dispControl &= FIELD_CLEAR(CRT_DISPLAY_CTRL, CLK);

	/* Set bit 29:27 of display control register for the right clock */
	/* Note that SM750LE only need to supported 7 resoluitons. */
	if (x == 800 && y == 600)
		dispControl = FIELD_SET(dispControl, CRT_DISPLAY_CTRL, CLK, PLL41);
	else if (x == 1024 && y == 768)
		dispControl = FIELD_SET(dispControl, CRT_DISPLAY_CTRL, CLK, PLL65);
	else if (x == 1152 && y == 864)
		dispControl = FIELD_SET(dispControl, CRT_DISPLAY_CTRL, CLK, PLL80);
	else if (x == 1280 && y == 768)
		dispControl = FIELD_SET(dispControl, CRT_DISPLAY_CTRL, CLK, PLL80);
	else if (x == 1280 && y == 720)
		dispControl = FIELD_SET(dispControl, CRT_DISPLAY_CTRL, CLK, PLL74);
	else if (x == 1280 && y == 960)
		dispControl = FIELD_SET(dispControl, CRT_DISPLAY_CTRL, CLK, PLL108);
	else if (x == 1280 && y == 1024)
		dispControl = FIELD_SET(dispControl, CRT_DISPLAY_CTRL, CLK, PLL108);
	else /* default to VGA clock */
	dispControl = FIELD_SET(dispControl, CRT_DISPLAY_CTRL, CLK, PLL25);

	/* Set bit 25:24 of display controller */
	dispControl = FIELD_SET(dispControl, CRT_DISPLAY_CTRL, CRTSELECT, CRT);
	dispControl = FIELD_SET(dispControl, CRT_DISPLAY_CTRL, RGBBIT, 24BIT);

	/* Set bit 14 of display controller */
	dispControl = FIELD_SET(dispControl, CRT_DISPLAY_CTRL, CLOCK_PHASE, ACTIVE_LOW);

	POKE32(CRT_DISPLAY_CTRL, dispControl);

	return dispControl;
}



/* only timing related registers will be  programed */
static int programModeRegisters(mode_parameter_t *pModeParam, pll_value_t *pll)
{
	int ret = 0;
	int cnt = 0;
	unsigned int ulTmpValue, ulReg;

	if (pll->clockType == SECONDARY_PLL) {
		/* programe secondary pixel clock */
		POKE32(CRT_PLL_CTRL, formatPllReg(pll));
		POKE32(CRT_HORIZONTAL_TOTAL,
		FIELD_VALUE(0, CRT_HORIZONTAL_TOTAL, TOTAL, pModeParam->horizontal_total - 1)
		| FIELD_VALUE(0, CRT_HORIZONTAL_TOTAL, DISPLAY_END, pModeParam->horizontal_display_end - 1));

		POKE32(CRT_HORIZONTAL_SYNC,
		FIELD_VALUE(0, CRT_HORIZONTAL_SYNC, WIDTH, pModeParam->horizontal_sync_width)
		| FIELD_VALUE(0, CRT_HORIZONTAL_SYNC, START, pModeParam->horizontal_sync_start - 1));

		POKE32(CRT_VERTICAL_TOTAL,
		FIELD_VALUE(0, CRT_VERTICAL_TOTAL, TOTAL, pModeParam->vertical_total - 1)
		| FIELD_VALUE(0, CRT_VERTICAL_TOTAL, DISPLAY_END, pModeParam->vertical_display_end - 1));

		POKE32(CRT_VERTICAL_SYNC,
		FIELD_VALUE(0, CRT_VERTICAL_SYNC, HEIGHT, pModeParam->vertical_sync_height)
		| FIELD_VALUE(0, CRT_VERTICAL_SYNC, START, pModeParam->vertical_sync_start - 1));


		ulTmpValue = FIELD_VALUE(0, CRT_DISPLAY_CTRL, VSYNC_PHASE, pModeParam->vertical_sync_polarity)|
					  FIELD_VALUE(0, CRT_DISPLAY_CTRL, HSYNC_PHASE, pModeParam->horizontal_sync_polarity)|
					  FIELD_SET(0, CRT_DISPLAY_CTRL, TIMING, ENABLE)|
					  FIELD_SET(0, CRT_DISPLAY_CTRL, PLANE, ENABLE);


		if (getChipType() == SM750LE) {
			displayControlAdjust_SM750LE(pModeParam, ulTmpValue);
		} else {
			ulReg = PEEK32(CRT_DISPLAY_CTRL)
					& FIELD_CLEAR(CRT_DISPLAY_CTRL, VSYNC_PHASE)
					& FIELD_CLEAR(CRT_DISPLAY_CTRL, HSYNC_PHASE)
					& FIELD_CLEAR(CRT_DISPLAY_CTRL, TIMING)
					& FIELD_CLEAR(CRT_DISPLAY_CTRL, PLANE);

			 POKE32(CRT_DISPLAY_CTRL, ulTmpValue|ulReg);
		}

	} else if (pll->clockType == PRIMARY_PLL) {
		unsigned int ulReservedBits;

		POKE32(PANEL_PLL_CTRL, formatPllReg(pll));

		POKE32(PANEL_HORIZONTAL_TOTAL,
		FIELD_VALUE(0, PANEL_HORIZONTAL_TOTAL, TOTAL, pModeParam->horizontal_total - 1)
		| FIELD_VALUE(0, PANEL_HORIZONTAL_TOTAL, DISPLAY_END, pModeParam->horizontal_display_end - 1));

		POKE32(PANEL_HORIZONTAL_SYNC,
		FIELD_VALUE(0, PANEL_HORIZONTAL_SYNC, WIDTH, pModeParam->horizontal_sync_width)
		| FIELD_VALUE(0, PANEL_HORIZONTAL_SYNC, START, pModeParam->horizontal_sync_start - 1));

		POKE32(PANEL_VERTICAL_TOTAL,
		FIELD_VALUE(0, PANEL_VERTICAL_TOTAL, TOTAL, pModeParam->vertical_total - 1)
			| FIELD_VALUE(0, PANEL_VERTICAL_TOTAL, DISPLAY_END, pModeParam->vertical_display_end - 1));

		POKE32(PANEL_VERTICAL_SYNC,
		FIELD_VALUE(0, PANEL_VERTICAL_SYNC, HEIGHT, pModeParam->vertical_sync_height)
		| FIELD_VALUE(0, PANEL_VERTICAL_SYNC, START, pModeParam->vertical_sync_start - 1));

		ulTmpValue = FIELD_VALUE(0, PANEL_DISPLAY_CTRL, VSYNC_PHASE, pModeParam->vertical_sync_polarity)|
			     FIELD_VALUE(0, PANEL_DISPLAY_CTRL, HSYNC_PHASE, pModeParam->horizontal_sync_polarity)|
			     FIELD_VALUE(0, PANEL_DISPLAY_CTRL, CLOCK_PHASE, pModeParam->clock_phase_polarity)|
			     FIELD_SET(0, PANEL_DISPLAY_CTRL, TIMING, ENABLE)|
			     FIELD_SET(0, PANEL_DISPLAY_CTRL, PLANE, ENABLE);

		ulReservedBits = FIELD_SET(0, PANEL_DISPLAY_CTRL, RESERVED_1_MASK, ENABLE) |
				 FIELD_SET(0, PANEL_DISPLAY_CTRL, RESERVED_2_MASK, ENABLE) |
				 FIELD_SET(0, PANEL_DISPLAY_CTRL, RESERVED_3_MASK, ENABLE)|
				 FIELD_SET(0, PANEL_DISPLAY_CTRL, VSYNC, ACTIVE_LOW);

		ulReg = (PEEK32(PANEL_DISPLAY_CTRL) & ~ulReservedBits)
			& FIELD_CLEAR(PANEL_DISPLAY_CTRL, CLOCK_PHASE)
			& FIELD_CLEAR(PANEL_DISPLAY_CTRL, VSYNC_PHASE)
			& FIELD_CLEAR(PANEL_DISPLAY_CTRL, HSYNC_PHASE)
			& FIELD_CLEAR(PANEL_DISPLAY_CTRL, TIMING)
			& FIELD_CLEAR(PANEL_DISPLAY_CTRL, PLANE);


		/* May a hardware bug or just my test chip (not confirmed).
		* PANEL_DISPLAY_CTRL register seems requiring few writes
		* before a value can be successfully written in.
		* Added some masks to mask out the reserved bits.
		* Note: This problem happens by design. The hardware will wait for the
		*       next vertical sync to turn on/off the plane.
		*/

		POKE32(PANEL_DISPLAY_CTRL, ulTmpValue|ulReg);

		while ((PEEK32(PANEL_DISPLAY_CTRL) & ~ulReservedBits) != (ulTmpValue|ulReg)) {
			cnt++;
			if (cnt > 1000)
				break;
			POKE32(PANEL_DISPLAY_CTRL, ulTmpValue|ulReg);
		}
	} else {
		ret = -1;
	}
	return ret;
}

int ddk750_setModeTiming(mode_parameter_t *parm, clock_type_t clock)
{
	pll_value_t pll;
	unsigned int uiActualPixelClk;

	pll.inputFreq = DEFAULT_INPUT_CLOCK;
	pll.clockType = clock;

	uiActualPixelClk = calcPllValue(parm->pixel_clock, &pll);
	if (getChipType() == SM750LE) {
		/* set graphic mode via IO method */
		outb_p(0x88, 0x3d4);
		outb_p(0x06, 0x3d5);
	}
	programModeRegisters(parm, &pll);
	return 0;
}