Commit | Line | Data |
---|---|---|
81dee67e SM |
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 | ||
da295041 | 7 | #define primaryWaitVerticalSync(delay) waitNextVerticalSync(0, delay) |
81dee67e | 8 | |
edb23022 | 9 | static void setDisplayControl(int ctrl, int disp_state) |
81dee67e SM |
10 | { |
11 | /* state != 0 means turn on both timing & plane en_bit */ | |
b117b637 MR |
12 | unsigned long reg, val, reserved; |
13 | int cnt = 0; | |
81dee67e | 14 | |
259fef35 | 15 | if (!ctrl) { |
b117b637 MR |
16 | reg = PANEL_DISPLAY_CTRL; |
17 | reserved = PANEL_DISPLAY_CTRL_RESERVED_MASK; | |
259fef35 | 18 | } else { |
b117b637 MR |
19 | reg = CRT_DISPLAY_CTRL; |
20 | reserved = CRT_DISPLAY_CTRL_RESERVED_MASK; | |
21 | } | |
81dee67e | 22 | |
b117b637 MR |
23 | val = PEEK32(reg); |
24 | if (disp_state) { | |
25 | /* | |
26 | * Timing should be enabled first before enabling the | |
27 | * plane because changing at the same time does not | |
28 | * guarantee that the plane will also enabled or | |
29 | * disabled. | |
30 | */ | |
6fba39cf | 31 | val |= DISPLAY_CTRL_TIMING; |
b117b637 MR |
32 | POKE32(reg, val); |
33 | ||
6fba39cf | 34 | val |= DISPLAY_CTRL_PLANE; |
b117b637 MR |
35 | |
36 | /* | |
37 | * Somehow the register value on the plane is not set | |
38 | * until a few delay. Need to write and read it a | |
39 | * couple times | |
40 | */ | |
41 | do { | |
42 | cnt++; | |
43 | POKE32(reg, val); | |
44 | } while ((PEEK32(reg) & ~reserved) != (val & ~reserved)); | |
45 | pr_debug("Set Plane enbit:after tried %d times\n", cnt); | |
46 | } else { | |
47 | /* | |
48 | * When turning off, there is no rule on the | |
49 | * programming sequence since whenever the clock is | |
50 | * off, then it does not matter whether the plane is | |
51 | * enabled or disabled. Note: Modifying the plane bit | |
52 | * will take effect on the next vertical sync. Need to | |
53 | * find out if it is necessary to wait for 1 vsync | |
54 | * before modifying the timing enable bit. | |
55 | */ | |
6fba39cf | 56 | val &= ~DISPLAY_CTRL_PLANE; |
b117b637 MR |
57 | POKE32(reg, val); |
58 | ||
6fba39cf | 59 | val &= ~DISPLAY_CTRL_TIMING; |
b117b637 | 60 | POKE32(reg, val); |
81dee67e SM |
61 | } |
62 | } | |
63 | ||
da295041 | 64 | static void waitNextVerticalSync(int ctrl, int delay) |
81dee67e SM |
65 | { |
66 | unsigned int status; | |
40403c1b | 67 | |
8c11f5a2 | 68 | if (!ctrl) { |
81dee67e SM |
69 | /* primary controller */ |
70 | ||
c9d67dc4 K |
71 | /* |
72 | * Do not wait when the Primary PLL is off or display control is | |
73 | * already off. This will prevent the software to wait forever. | |
74 | */ | |
5557eb17 | 75 | if (!(PEEK32(PANEL_PLL_CTRL) & PLL_CTRL_POWER) || |
6fba39cf | 76 | !(PEEK32(PANEL_DISPLAY_CTRL) & DISPLAY_CTRL_TIMING)) { |
81dee67e SM |
77 | return; |
78 | } | |
79 | ||
259fef35 | 80 | while (delay-- > 0) { |
78376535 | 81 | /* Wait for end of vsync. */ |
259fef35 | 82 | do { |
410c756d MR |
83 | status = PEEK32(SYSTEM_CTRL); |
84 | } while (status & SYSTEM_CTRL_PANEL_VSYNC_ACTIVE); | |
78376535 JL |
85 | |
86 | /* Wait for start of vsync. */ | |
259fef35 | 87 | do { |
410c756d MR |
88 | status = PEEK32(SYSTEM_CTRL); |
89 | } while (!(status & SYSTEM_CTRL_PANEL_VSYNC_ACTIVE)); | |
78376535 | 90 | } |
81dee67e | 91 | |
6338a781 | 92 | } else { |
c9d67dc4 K |
93 | /* |
94 | * Do not wait when the Primary PLL is off or display control is | |
95 | * already off. This will prevent the software to wait forever. | |
96 | */ | |
5557eb17 | 97 | if (!(PEEK32(CRT_PLL_CTRL) & PLL_CTRL_POWER) || |
6fba39cf | 98 | !(PEEK32(CRT_DISPLAY_CTRL) & DISPLAY_CTRL_TIMING)) { |
81dee67e SM |
99 | return; |
100 | } | |
101 | ||
259fef35 | 102 | while (delay-- > 0) { |
81dee67e | 103 | /* Wait for end of vsync. */ |
259fef35 | 104 | do { |
410c756d MR |
105 | status = PEEK32(SYSTEM_CTRL); |
106 | } while (status & SYSTEM_CTRL_PANEL_VSYNC_ACTIVE); | |
81dee67e SM |
107 | |
108 | /* Wait for start of vsync. */ | |
259fef35 | 109 | do { |
410c756d MR |
110 | status = PEEK32(SYSTEM_CTRL); |
111 | } while (!(status & SYSTEM_CTRL_PANEL_VSYNC_ACTIVE)); | |
81dee67e SM |
112 | } |
113 | } | |
114 | } | |
115 | ||
da295041 | 116 | static void swPanelPowerSequence(int disp, int delay) |
81dee67e SM |
117 | { |
118 | unsigned int reg; | |
119 | ||
120 | /* disp should be 1 to open sequence */ | |
121 | reg = PEEK32(PANEL_DISPLAY_CTRL); | |
6fba39cf | 122 | reg |= (disp ? PANEL_DISPLAY_CTRL_FPEN : 0); |
da295041 | 123 | POKE32(PANEL_DISPLAY_CTRL, reg); |
81dee67e SM |
124 | primaryWaitVerticalSync(delay); |
125 | ||
81dee67e | 126 | reg = PEEK32(PANEL_DISPLAY_CTRL); |
6fba39cf | 127 | reg |= (disp ? PANEL_DISPLAY_CTRL_DATA : 0); |
da295041 | 128 | POKE32(PANEL_DISPLAY_CTRL, reg); |
81dee67e SM |
129 | primaryWaitVerticalSync(delay); |
130 | ||
131 | reg = PEEK32(PANEL_DISPLAY_CTRL); | |
6fba39cf | 132 | reg |= (disp ? PANEL_DISPLAY_CTRL_VBIASEN : 0); |
da295041 | 133 | POKE32(PANEL_DISPLAY_CTRL, reg); |
81dee67e SM |
134 | primaryWaitVerticalSync(delay); |
135 | ||
81dee67e | 136 | reg = PEEK32(PANEL_DISPLAY_CTRL); |
6fba39cf | 137 | reg |= (disp ? PANEL_DISPLAY_CTRL_FPEN : 0); |
da295041 | 138 | POKE32(PANEL_DISPLAY_CTRL, reg); |
81dee67e SM |
139 | primaryWaitVerticalSync(delay); |
140 | ||
141 | } | |
142 | ||
143 | void ddk750_setLogicalDispOut(disp_output_t output) | |
144 | { | |
145 | unsigned int reg; | |
40403c1b | 146 | |
8c11f5a2 | 147 | if (output & PNL_2_USAGE) { |
81dee67e SM |
148 | /* set panel path controller select */ |
149 | reg = PEEK32(PANEL_DISPLAY_CTRL); | |
c4e893b7 MR |
150 | reg &= ~PANEL_DISPLAY_CTRL_SELECT_MASK; |
151 | reg |= (((output & PNL_2_MASK) >> PNL_2_OFFSET) << | |
152 | PANEL_DISPLAY_CTRL_SELECT_SHIFT); | |
da295041 | 153 | POKE32(PANEL_DISPLAY_CTRL, reg); |
81dee67e SM |
154 | } |
155 | ||
8c11f5a2 | 156 | if (output & CRT_2_USAGE) { |
81dee67e SM |
157 | /* set crt path controller select */ |
158 | reg = PEEK32(CRT_DISPLAY_CTRL); | |
cdce1f18 MR |
159 | reg &= ~CRT_DISPLAY_CTRL_SELECT_MASK; |
160 | reg |= (((output & CRT_2_MASK) >> CRT_2_OFFSET) << | |
161 | CRT_DISPLAY_CTRL_SELECT_SHIFT); | |
81dee67e | 162 | /*se blank off */ |
d8264edf | 163 | reg &= ~CRT_DISPLAY_CTRL_BLANK; |
da295041 | 164 | POKE32(CRT_DISPLAY_CTRL, reg); |
81dee67e SM |
165 | |
166 | } | |
167 | ||
8c11f5a2 | 168 | if (output & PRI_TP_USAGE) { |
81dee67e | 169 | /* set primary timing and plane en_bit */ |
aeec43da | 170 | setDisplayControl(0, (output & PRI_TP_MASK) >> PRI_TP_OFFSET); |
81dee67e SM |
171 | } |
172 | ||
8c11f5a2 | 173 | if (output & SEC_TP_USAGE) { |
81dee67e | 174 | /* set secondary timing and plane en_bit*/ |
aeec43da | 175 | setDisplayControl(1, (output & SEC_TP_MASK) >> SEC_TP_OFFSET); |
81dee67e SM |
176 | } |
177 | ||
8c11f5a2 | 178 | if (output & PNL_SEQ_USAGE) { |
81dee67e | 179 | /* set panel sequence */ |
aeec43da | 180 | swPanelPowerSequence((output & PNL_SEQ_MASK) >> PNL_SEQ_OFFSET, 4); |
81dee67e SM |
181 | } |
182 | ||
9ccc5f44 | 183 | if (output & DAC_USAGE) |
e80ef45d | 184 | setDAC((output & DAC_MASK) >> DAC_OFFSET); |
81dee67e | 185 | |
9ccc5f44 | 186 | if (output & DPMS_USAGE) |
81dee67e SM |
187 | ddk750_setDPMS((output & DPMS_MASK) >> DPMS_OFFSET); |
188 | } |