1
2#include "ddk750_help.h"
3#include "ddk750_reg.h"
4#include "ddk750_mode.h"
5#include "ddk750_chip.h"
6
7/*
8	SM750LE only:
9    This function takes care extra registers and bit fields required to set
10    up a mode in SM750LE
11
12	Explanation about Display Control register:
13    HW only supports 7 predefined pixel clocks, and clock select is
14    in bit 29:27 of	Display Control register.
15*/
16static unsigned long displayControlAdjust_SM750LE(mode_parameter_t *pModeParam, unsigned long dispControl)
17{
18	unsigned long x, y;
19
20	x = pModeParam->horizontal_display_end;
21	y = pModeParam->vertical_display_end;
22
23	/* SM750LE has to set up the top-left and bottom-right
24	   registers as well.
25	   Note that normal SM750/SM718 only use those two register for
26	   auto-centering mode.
27	 */
28	POKE32(CRT_AUTO_CENTERING_TL,
29	FIELD_VALUE(0, CRT_AUTO_CENTERING_TL, TOP, 0)
30	| FIELD_VALUE(0, CRT_AUTO_CENTERING_TL, LEFT, 0));
31
32	POKE32(CRT_AUTO_CENTERING_BR,
33	FIELD_VALUE(0, CRT_AUTO_CENTERING_BR, BOTTOM, y-1)
34	| FIELD_VALUE(0, CRT_AUTO_CENTERING_BR, RIGHT, x-1));
35
36	/* Assume common fields in dispControl have been properly set before
37	   calling this function.
38	   This function only sets the extra fields in dispControl.
39	 */
40
41	/* Clear bit 29:27 of display control register */
42	dispControl &= FIELD_CLEAR(CRT_DISPLAY_CTRL, CLK);
43
44	/* Set bit 29:27 of display control register for the right clock */
45	/* Note that SM750LE only need to supported 7 resoluitons. */
46	if (x == 800 && y == 600)
47		dispControl = FIELD_SET(dispControl, CRT_DISPLAY_CTRL, CLK, PLL41);
48	else if (x == 1024 && y == 768)
49		dispControl = FIELD_SET(dispControl, CRT_DISPLAY_CTRL, CLK, PLL65);
50	else if (x == 1152 && y == 864)
51		dispControl = FIELD_SET(dispControl, CRT_DISPLAY_CTRL, CLK, PLL80);
52	else if (x == 1280 && y == 768)
53		dispControl = FIELD_SET(dispControl, CRT_DISPLAY_CTRL, CLK, PLL80);
54	else if (x == 1280 && y == 720)
55		dispControl = FIELD_SET(dispControl, CRT_DISPLAY_CTRL, CLK, PLL74);
56	else if (x == 1280 && y == 960)
57		dispControl = FIELD_SET(dispControl, CRT_DISPLAY_CTRL, CLK, PLL108);
58	else if (x == 1280 && y == 1024)
59		dispControl = FIELD_SET(dispControl, CRT_DISPLAY_CTRL, CLK, PLL108);
60	else /* default to VGA clock */
61	dispControl = FIELD_SET(dispControl, CRT_DISPLAY_CTRL, CLK, PLL25);
62
63	/* Set bit 25:24 of display controller */
64	dispControl = FIELD_SET(dispControl, CRT_DISPLAY_CTRL, CRTSELECT, CRT);
65	dispControl = FIELD_SET(dispControl, CRT_DISPLAY_CTRL, RGBBIT, 24BIT);
66
67	/* Set bit 14 of display controller */
68	dispControl = FIELD_SET(dispControl, CRT_DISPLAY_CTRL, CLOCK_PHASE, ACTIVE_LOW);
69
70	POKE32(CRT_DISPLAY_CTRL, dispControl);
71
72	return dispControl;
73}
74
75
76
77/* only timing related registers will be  programed */
78static int programModeRegisters(mode_parameter_t *pModeParam, pll_value_t *pll)
79{
80	int ret = 0;
81	int cnt = 0;
82	unsigned int ulTmpValue, ulReg;
83
84	if (pll->clockType == SECONDARY_PLL) {
85		/* programe secondary pixel clock */
86		POKE32(CRT_PLL_CTRL, formatPllReg(pll));
87		POKE32(CRT_HORIZONTAL_TOTAL,
88		FIELD_VALUE(0, CRT_HORIZONTAL_TOTAL, TOTAL, pModeParam->horizontal_total - 1)
89		| FIELD_VALUE(0, CRT_HORIZONTAL_TOTAL, DISPLAY_END, pModeParam->horizontal_display_end - 1));
90
91		POKE32(CRT_HORIZONTAL_SYNC,
92		FIELD_VALUE(0, CRT_HORIZONTAL_SYNC, WIDTH, pModeParam->horizontal_sync_width)
93		| FIELD_VALUE(0, CRT_HORIZONTAL_SYNC, START, pModeParam->horizontal_sync_start - 1));
94
95		POKE32(CRT_VERTICAL_TOTAL,
96		FIELD_VALUE(0, CRT_VERTICAL_TOTAL, TOTAL, pModeParam->vertical_total - 1)
97		| FIELD_VALUE(0, CRT_VERTICAL_TOTAL, DISPLAY_END, pModeParam->vertical_display_end - 1));
98
99		POKE32(CRT_VERTICAL_SYNC,
100		FIELD_VALUE(0, CRT_VERTICAL_SYNC, HEIGHT, pModeParam->vertical_sync_height)
101		| FIELD_VALUE(0, CRT_VERTICAL_SYNC, START, pModeParam->vertical_sync_start - 1));
102
103
104		ulTmpValue = FIELD_VALUE(0, CRT_DISPLAY_CTRL, VSYNC_PHASE, pModeParam->vertical_sync_polarity)|
105					  FIELD_VALUE(0, CRT_DISPLAY_CTRL, HSYNC_PHASE, pModeParam->horizontal_sync_polarity)|
106					  FIELD_SET(0, CRT_DISPLAY_CTRL, TIMING, ENABLE)|
107					  FIELD_SET(0, CRT_DISPLAY_CTRL, PLANE, ENABLE);
108
109
110		if (getChipType() == SM750LE) {
111			displayControlAdjust_SM750LE(pModeParam, ulTmpValue);
112		} else {
113			ulReg = PEEK32(CRT_DISPLAY_CTRL)
114					& FIELD_CLEAR(CRT_DISPLAY_CTRL, VSYNC_PHASE)
115					& FIELD_CLEAR(CRT_DISPLAY_CTRL, HSYNC_PHASE)
116					& FIELD_CLEAR(CRT_DISPLAY_CTRL, TIMING)
117					& FIELD_CLEAR(CRT_DISPLAY_CTRL, PLANE);
118
119			 POKE32(CRT_DISPLAY_CTRL, ulTmpValue|ulReg);
120		}
121
122	} else if (pll->clockType == PRIMARY_PLL) {
123		unsigned int ulReservedBits;
124
125		POKE32(PANEL_PLL_CTRL, formatPllReg(pll));
126
127		POKE32(PANEL_HORIZONTAL_TOTAL,
128		FIELD_VALUE(0, PANEL_HORIZONTAL_TOTAL, TOTAL, pModeParam->horizontal_total - 1)
129		| FIELD_VALUE(0, PANEL_HORIZONTAL_TOTAL, DISPLAY_END, pModeParam->horizontal_display_end - 1));
130
131		POKE32(PANEL_HORIZONTAL_SYNC,
132		FIELD_VALUE(0, PANEL_HORIZONTAL_SYNC, WIDTH, pModeParam->horizontal_sync_width)
133		| FIELD_VALUE(0, PANEL_HORIZONTAL_SYNC, START, pModeParam->horizontal_sync_start - 1));
134
135		POKE32(PANEL_VERTICAL_TOTAL,
136		FIELD_VALUE(0, PANEL_VERTICAL_TOTAL, TOTAL, pModeParam->vertical_total - 1)
137			| FIELD_VALUE(0, PANEL_VERTICAL_TOTAL, DISPLAY_END, pModeParam->vertical_display_end - 1));
138
139		POKE32(PANEL_VERTICAL_SYNC,
140		FIELD_VALUE(0, PANEL_VERTICAL_SYNC, HEIGHT, pModeParam->vertical_sync_height)
141		| FIELD_VALUE(0, PANEL_VERTICAL_SYNC, START, pModeParam->vertical_sync_start - 1));
142
143		ulTmpValue = FIELD_VALUE(0, PANEL_DISPLAY_CTRL, VSYNC_PHASE, pModeParam->vertical_sync_polarity)|
144			     FIELD_VALUE(0, PANEL_DISPLAY_CTRL, HSYNC_PHASE, pModeParam->horizontal_sync_polarity)|
145			     FIELD_VALUE(0, PANEL_DISPLAY_CTRL, CLOCK_PHASE, pModeParam->clock_phase_polarity)|
146			     FIELD_SET(0, PANEL_DISPLAY_CTRL, TIMING, ENABLE)|
147			     FIELD_SET(0, PANEL_DISPLAY_CTRL, PLANE, ENABLE);
148
149		ulReservedBits = FIELD_SET(0, PANEL_DISPLAY_CTRL, RESERVED_1_MASK, ENABLE) |
150				 FIELD_SET(0, PANEL_DISPLAY_CTRL, RESERVED_2_MASK, ENABLE) |
151				 FIELD_SET(0, PANEL_DISPLAY_CTRL, RESERVED_3_MASK, ENABLE)|
152				 FIELD_SET(0, PANEL_DISPLAY_CTRL, VSYNC, ACTIVE_LOW);
153
154		ulReg = (PEEK32(PANEL_DISPLAY_CTRL) & ~ulReservedBits)
155			& FIELD_CLEAR(PANEL_DISPLAY_CTRL, CLOCK_PHASE)
156			& FIELD_CLEAR(PANEL_DISPLAY_CTRL, VSYNC_PHASE)
157			& FIELD_CLEAR(PANEL_DISPLAY_CTRL, HSYNC_PHASE)
158			& FIELD_CLEAR(PANEL_DISPLAY_CTRL, TIMING)
159			& FIELD_CLEAR(PANEL_DISPLAY_CTRL, PLANE);
160
161
162		/* May a hardware bug or just my test chip (not confirmed).
163		* PANEL_DISPLAY_CTRL register seems requiring few writes
164		* before a value can be successfully written in.
165		* Added some masks to mask out the reserved bits.
166		* Note: This problem happens by design. The hardware will wait for the
167		*       next vertical sync to turn on/off the plane.
168		*/
169
170		POKE32(PANEL_DISPLAY_CTRL, ulTmpValue|ulReg);
171
172		while ((PEEK32(PANEL_DISPLAY_CTRL) & ~ulReservedBits) != (ulTmpValue|ulReg)) {
173			cnt++;
174			if (cnt > 1000)
175				break;
176			POKE32(PANEL_DISPLAY_CTRL, ulTmpValue|ulReg);
177		}
178	} else {
179		ret = -1;
180	}
181	return ret;
182}
183
184int ddk750_setModeTiming(mode_parameter_t *parm, clock_type_t clock)
185{
186	pll_value_t pll;
187	unsigned int uiActualPixelClk;
188
189	pll.inputFreq = DEFAULT_INPUT_CLOCK;
190	pll.clockType = clock;
191
192	uiActualPixelClk = calcPllValue(parm->pixel_clock, &pll);
193	if (getChipType() == SM750LE) {
194		/* set graphic mode via IO method */
195		outb_p(0x88, 0x3d4);
196		outb_p(0x06, 0x3d5);
197	}
198	programModeRegisters(parm, &pll);
199	return 0;
200}
201
202
203