1#include "ddk750_reg.h"
2#include "ddk750_help.h"
3#include "ddk750_display.h"
4#include "ddk750_power.h"
5#include "ddk750_dvi.h"
6
7#define primaryWaitVerticalSync(delay) waitNextVerticalSync(0, delay)
8
9static void setDisplayControl(int ctrl, int disp_state)
10{
11	/* state != 0 means turn on both timing & plane en_bit */
12	unsigned long ulDisplayCtrlReg, ulReservedBits;
13	int cnt;
14
15	cnt = 0;
16
17	/* Set the primary display control */
18	if (!ctrl) {
19		ulDisplayCtrlReg = PEEK32(PANEL_DISPLAY_CTRL);
20		/* Turn on/off the Panel display control */
21		if (disp_state) {
22			/* Timing should be enabled first before enabling the plane
23			 * because changing at the same time does not guarantee that
24			 * the plane will also enabled or disabled.
25			 */
26			ulDisplayCtrlReg = FIELD_SET(ulDisplayCtrlReg,
27								PANEL_DISPLAY_CTRL, TIMING, ENABLE);
28			POKE32(PANEL_DISPLAY_CTRL, ulDisplayCtrlReg);
29
30			ulDisplayCtrlReg = FIELD_SET(ulDisplayCtrlReg,
31								PANEL_DISPLAY_CTRL, PLANE, ENABLE);
32
33			/* Added some masks to mask out the reserved bits.
34			 * Sometimes, the reserved bits are set/reset randomly when
35			 * writing to the PRIMARY_DISPLAY_CTRL, therefore, the register
36			 * reserved bits are needed to be masked out.
37			 */
38			ulReservedBits = FIELD_SET(0, PANEL_DISPLAY_CTRL, RESERVED_1_MASK, ENABLE) |
39				FIELD_SET(0, PANEL_DISPLAY_CTRL, RESERVED_2_MASK, ENABLE) |
40				FIELD_SET(0, PANEL_DISPLAY_CTRL, RESERVED_3_MASK, ENABLE);
41
42			/* Somehow the register value on the plane is not set
43			 * until a few delay. Need to write
44			 * and read it a couple times
45			 */
46			do {
47				cnt++;
48				POKE32(PANEL_DISPLAY_CTRL, ulDisplayCtrlReg);
49			} while ((PEEK32(PANEL_DISPLAY_CTRL) & ~ulReservedBits) !=
50					(ulDisplayCtrlReg & ~ulReservedBits));
51			printk("Set Panel Plane enbit:after tried %d times\n", cnt);
52		} else {
53			/* When turning off, there is no rule on the programming
54			 * sequence since whenever the clock is off, then it does not
55			 * matter whether the plane is enabled or disabled.
56			 * Note: Modifying the plane bit will take effect on the
57			 * next vertical sync. Need to find out if it is necessary to
58			 * wait for 1 vsync before modifying the timing enable bit.
59			 * */
60			ulDisplayCtrlReg = FIELD_SET(ulDisplayCtrlReg,
61								PANEL_DISPLAY_CTRL, PLANE, DISABLE);
62			POKE32(PANEL_DISPLAY_CTRL, ulDisplayCtrlReg);
63
64			ulDisplayCtrlReg = FIELD_SET(ulDisplayCtrlReg,
65								PANEL_DISPLAY_CTRL, TIMING, DISABLE);
66			POKE32(PANEL_DISPLAY_CTRL, ulDisplayCtrlReg);
67		}
68
69	} else {
70		/* Set the secondary display control */
71		ulDisplayCtrlReg = PEEK32(CRT_DISPLAY_CTRL);
72
73		if (disp_state) {
74			/* Timing should be enabled first before enabling the plane because changing at the
75			   same time does not guarantee that the plane will also enabled or disabled.
76			   */
77			ulDisplayCtrlReg = FIELD_SET(ulDisplayCtrlReg,
78								CRT_DISPLAY_CTRL, TIMING, ENABLE);
79			POKE32(CRT_DISPLAY_CTRL, ulDisplayCtrlReg);
80
81			ulDisplayCtrlReg = FIELD_SET(ulDisplayCtrlReg,
82								CRT_DISPLAY_CTRL, PLANE, ENABLE);
83
84			/* Added some masks to mask out the reserved bits.
85			 * Sometimes, the reserved bits are set/reset randomly when
86			 * writing to the PRIMARY_DISPLAY_CTRL, therefore, the register
87			 * reserved bits are needed to be masked out.
88			 */
89
90			ulReservedBits = FIELD_SET(0, CRT_DISPLAY_CTRL, RESERVED_1_MASK, ENABLE) |
91				FIELD_SET(0, CRT_DISPLAY_CTRL, RESERVED_2_MASK, ENABLE) |
92				FIELD_SET(0, CRT_DISPLAY_CTRL, RESERVED_3_MASK, ENABLE) |
93				FIELD_SET(0, CRT_DISPLAY_CTRL, RESERVED_4_MASK, ENABLE);
94
95			do {
96				cnt++;
97				POKE32(CRT_DISPLAY_CTRL, ulDisplayCtrlReg);
98			} while ((PEEK32(CRT_DISPLAY_CTRL) & ~ulReservedBits) !=
99					(ulDisplayCtrlReg & ~ulReservedBits));
100				printk("Set Crt Plane enbit:after tried %d times\n", cnt);
101		} else {
102			/* When turning off, there is no rule on the programming
103			 * sequence since whenever the clock is off, then it does not
104			 * matter whether the plane is enabled or disabled.
105			 * Note: Modifying the plane bit will take effect on the next
106			 * vertical sync. Need to find out if it is necessary to
107			 * wait for 1 vsync before modifying the timing enable bit.
108			 */
109			ulDisplayCtrlReg = FIELD_SET(ulDisplayCtrlReg,
110								CRT_DISPLAY_CTRL, PLANE, DISABLE);
111			POKE32(CRT_DISPLAY_CTRL, ulDisplayCtrlReg);
112
113			ulDisplayCtrlReg = FIELD_SET(ulDisplayCtrlReg,
114								CRT_DISPLAY_CTRL, TIMING, DISABLE);
115			POKE32(CRT_DISPLAY_CTRL, ulDisplayCtrlReg);
116		}
117	}
118}
119
120static void waitNextVerticalSync(int ctrl, int delay)
121{
122	unsigned int status;
123
124	if (!ctrl) {
125		/* primary controller */
126
127		/* Do not wait when the Primary PLL is off or display control is already off.
128		   This will prevent the software to wait forever. */
129		if ((FIELD_GET(PEEK32(PANEL_PLL_CTRL), PANEL_PLL_CTRL, POWER) ==
130			 PANEL_PLL_CTRL_POWER_OFF) ||
131			(FIELD_GET(PEEK32(PANEL_DISPLAY_CTRL), PANEL_DISPLAY_CTRL, TIMING) ==
132			 PANEL_DISPLAY_CTRL_TIMING_DISABLE)) {
133			return;
134		}
135
136		while (delay-- > 0) {
137			/* Wait for end of vsync. */
138			do {
139				status = FIELD_GET(PEEK32(SYSTEM_CTRL),
140						   SYSTEM_CTRL,
141						   PANEL_VSYNC);
142			} while (status == SYSTEM_CTRL_PANEL_VSYNC_ACTIVE);
143
144			/* Wait for start of vsync. */
145			do {
146				status = FIELD_GET(PEEK32(SYSTEM_CTRL),
147						   SYSTEM_CTRL,
148						   PANEL_VSYNC);
149			} while (status == SYSTEM_CTRL_PANEL_VSYNC_INACTIVE);
150		}
151
152	} else {
153
154		/* Do not wait when the Primary PLL is off or display control is already off.
155			   This will prevent the software to wait forever. */
156		if ((FIELD_GET(PEEK32(CRT_PLL_CTRL), CRT_PLL_CTRL, POWER) ==
157			 CRT_PLL_CTRL_POWER_OFF) ||
158			(FIELD_GET(PEEK32(CRT_DISPLAY_CTRL), CRT_DISPLAY_CTRL, TIMING) ==
159			 CRT_DISPLAY_CTRL_TIMING_DISABLE)) {
160			return;
161		}
162
163		while (delay-- > 0) {
164			/* Wait for end of vsync. */
165			do {
166				status = FIELD_GET(PEEK32(SYSTEM_CTRL),
167								   SYSTEM_CTRL,
168								   CRT_VSYNC);
169			} while (status == SYSTEM_CTRL_CRT_VSYNC_ACTIVE);
170
171			/* Wait for start of vsync. */
172			do {
173				status = FIELD_GET(PEEK32(SYSTEM_CTRL),
174								   SYSTEM_CTRL,
175								   CRT_VSYNC);
176			} while (status == SYSTEM_CTRL_CRT_VSYNC_INACTIVE);
177		}
178	}
179}
180
181static void swPanelPowerSequence(int disp, int delay)
182{
183	unsigned int reg;
184
185	/* disp should be 1 to open sequence */
186	reg = PEEK32(PANEL_DISPLAY_CTRL);
187	reg = FIELD_VALUE(reg, PANEL_DISPLAY_CTRL, FPEN, disp);
188	POKE32(PANEL_DISPLAY_CTRL, reg);
189	primaryWaitVerticalSync(delay);
190
191	reg = PEEK32(PANEL_DISPLAY_CTRL);
192	reg = FIELD_VALUE(reg, PANEL_DISPLAY_CTRL, DATA, disp);
193	POKE32(PANEL_DISPLAY_CTRL, reg);
194	primaryWaitVerticalSync(delay);
195
196	reg = PEEK32(PANEL_DISPLAY_CTRL);
197	reg = FIELD_VALUE(reg, PANEL_DISPLAY_CTRL, VBIASEN, disp);
198	POKE32(PANEL_DISPLAY_CTRL, reg);
199	primaryWaitVerticalSync(delay);
200
201	reg = PEEK32(PANEL_DISPLAY_CTRL);
202	reg = FIELD_VALUE(reg, PANEL_DISPLAY_CTRL, FPEN, disp);
203	POKE32(PANEL_DISPLAY_CTRL, reg);
204	primaryWaitVerticalSync(delay);
205
206}
207
208void ddk750_setLogicalDispOut(disp_output_t output)
209{
210	unsigned int reg;
211
212	if (output & PNL_2_USAGE) {
213		/* set panel path controller select */
214		reg = PEEK32(PANEL_DISPLAY_CTRL);
215		reg = FIELD_VALUE(reg, PANEL_DISPLAY_CTRL, SELECT, (output & PNL_2_MASK)>>PNL_2_OFFSET);
216		POKE32(PANEL_DISPLAY_CTRL, reg);
217	}
218
219	if (output & CRT_2_USAGE) {
220		/* set crt path controller select */
221		reg = PEEK32(CRT_DISPLAY_CTRL);
222		reg = FIELD_VALUE(reg, CRT_DISPLAY_CTRL, SELECT, (output & CRT_2_MASK)>>CRT_2_OFFSET);
223		/*se blank off */
224		reg = FIELD_SET(reg, CRT_DISPLAY_CTRL, BLANK, OFF);
225		POKE32(CRT_DISPLAY_CTRL, reg);
226
227	}
228
229	if (output & PRI_TP_USAGE) {
230		/* set primary timing and plane en_bit */
231		setDisplayControl(0, (output & PRI_TP_MASK) >> PRI_TP_OFFSET);
232	}
233
234	if (output & SEC_TP_USAGE) {
235		/* set secondary timing and plane en_bit*/
236		setDisplayControl(1, (output & SEC_TP_MASK) >> SEC_TP_OFFSET);
237	}
238
239	if (output & PNL_SEQ_USAGE) {
240		/* set  panel sequence */
241		swPanelPowerSequence((output & PNL_SEQ_MASK) >> PNL_SEQ_OFFSET, 4);
242	}
243
244	if (output & DAC_USAGE)
245		setDAC((output & DAC_MASK) >> DAC_OFFSET);
246
247	if (output & DPMS_USAGE)
248		ddk750_setDPMS((output & DPMS_MASK) >> DPMS_OFFSET);
249}
250