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 | ||
78376535 JL |
71 | /* Do not wait when the Primary PLL is off or display control is already off. |
72 | This will prevent the software to wait forever. */ | |
5557eb17 | 73 | if (!(PEEK32(PANEL_PLL_CTRL) & PLL_CTRL_POWER) || |
6fba39cf | 74 | !(PEEK32(PANEL_DISPLAY_CTRL) & DISPLAY_CTRL_TIMING)) { |
81dee67e SM |
75 | return; |
76 | } | |
77 | ||
259fef35 | 78 | while (delay-- > 0) { |
78376535 | 79 | /* Wait for end of vsync. */ |
259fef35 | 80 | do { |
410c756d MR |
81 | status = PEEK32(SYSTEM_CTRL); |
82 | } while (status & SYSTEM_CTRL_PANEL_VSYNC_ACTIVE); | |
78376535 JL |
83 | |
84 | /* Wait for start of vsync. */ | |
259fef35 | 85 | do { |
410c756d MR |
86 | status = PEEK32(SYSTEM_CTRL); |
87 | } while (!(status & SYSTEM_CTRL_PANEL_VSYNC_ACTIVE)); | |
78376535 | 88 | } |
81dee67e | 89 | |
6338a781 | 90 | } else { |
81dee67e SM |
91 | |
92 | /* Do not wait when the Primary PLL is off or display control is already off. | |
93 | This will prevent the software to wait forever. */ | |
5557eb17 | 94 | if (!(PEEK32(CRT_PLL_CTRL) & PLL_CTRL_POWER) || |
6fba39cf | 95 | !(PEEK32(CRT_DISPLAY_CTRL) & DISPLAY_CTRL_TIMING)) { |
81dee67e SM |
96 | return; |
97 | } | |
98 | ||
259fef35 | 99 | while (delay-- > 0) { |
81dee67e | 100 | /* Wait for end of vsync. */ |
259fef35 | 101 | do { |
410c756d MR |
102 | status = PEEK32(SYSTEM_CTRL); |
103 | } while (status & SYSTEM_CTRL_PANEL_VSYNC_ACTIVE); | |
81dee67e SM |
104 | |
105 | /* Wait for start of vsync. */ | |
259fef35 | 106 | do { |
410c756d MR |
107 | status = PEEK32(SYSTEM_CTRL); |
108 | } while (!(status & SYSTEM_CTRL_PANEL_VSYNC_ACTIVE)); | |
81dee67e SM |
109 | } |
110 | } | |
111 | } | |
112 | ||
da295041 | 113 | static void swPanelPowerSequence(int disp, int delay) |
81dee67e SM |
114 | { |
115 | unsigned int reg; | |
116 | ||
117 | /* disp should be 1 to open sequence */ | |
118 | reg = PEEK32(PANEL_DISPLAY_CTRL); | |
6fba39cf | 119 | reg |= (disp ? PANEL_DISPLAY_CTRL_FPEN : 0); |
da295041 | 120 | POKE32(PANEL_DISPLAY_CTRL, reg); |
81dee67e SM |
121 | primaryWaitVerticalSync(delay); |
122 | ||
81dee67e | 123 | reg = PEEK32(PANEL_DISPLAY_CTRL); |
6fba39cf | 124 | reg |= (disp ? PANEL_DISPLAY_CTRL_DATA : 0); |
da295041 | 125 | POKE32(PANEL_DISPLAY_CTRL, reg); |
81dee67e SM |
126 | primaryWaitVerticalSync(delay); |
127 | ||
128 | reg = PEEK32(PANEL_DISPLAY_CTRL); | |
6fba39cf | 129 | reg |= (disp ? PANEL_DISPLAY_CTRL_VBIASEN : 0); |
da295041 | 130 | POKE32(PANEL_DISPLAY_CTRL, reg); |
81dee67e SM |
131 | primaryWaitVerticalSync(delay); |
132 | ||
81dee67e | 133 | reg = PEEK32(PANEL_DISPLAY_CTRL); |
6fba39cf | 134 | reg |= (disp ? PANEL_DISPLAY_CTRL_FPEN : 0); |
da295041 | 135 | POKE32(PANEL_DISPLAY_CTRL, reg); |
81dee67e SM |
136 | primaryWaitVerticalSync(delay); |
137 | ||
138 | } | |
139 | ||
140 | void ddk750_setLogicalDispOut(disp_output_t output) | |
141 | { | |
142 | unsigned int reg; | |
40403c1b | 143 | |
8c11f5a2 | 144 | if (output & PNL_2_USAGE) { |
81dee67e SM |
145 | /* set panel path controller select */ |
146 | reg = PEEK32(PANEL_DISPLAY_CTRL); | |
c4e893b7 MR |
147 | reg &= ~PANEL_DISPLAY_CTRL_SELECT_MASK; |
148 | reg |= (((output & PNL_2_MASK) >> PNL_2_OFFSET) << | |
149 | PANEL_DISPLAY_CTRL_SELECT_SHIFT); | |
da295041 | 150 | POKE32(PANEL_DISPLAY_CTRL, reg); |
81dee67e SM |
151 | } |
152 | ||
8c11f5a2 | 153 | if (output & CRT_2_USAGE) { |
81dee67e SM |
154 | /* set crt path controller select */ |
155 | reg = PEEK32(CRT_DISPLAY_CTRL); | |
cdce1f18 MR |
156 | reg &= ~CRT_DISPLAY_CTRL_SELECT_MASK; |
157 | reg |= (((output & CRT_2_MASK) >> CRT_2_OFFSET) << | |
158 | CRT_DISPLAY_CTRL_SELECT_SHIFT); | |
81dee67e | 159 | /*se blank off */ |
d8264edf | 160 | reg &= ~CRT_DISPLAY_CTRL_BLANK; |
da295041 | 161 | POKE32(CRT_DISPLAY_CTRL, reg); |
81dee67e SM |
162 | |
163 | } | |
164 | ||
8c11f5a2 | 165 | if (output & PRI_TP_USAGE) { |
81dee67e | 166 | /* set primary timing and plane en_bit */ |
aeec43da | 167 | setDisplayControl(0, (output & PRI_TP_MASK) >> PRI_TP_OFFSET); |
81dee67e SM |
168 | } |
169 | ||
8c11f5a2 | 170 | if (output & SEC_TP_USAGE) { |
81dee67e | 171 | /* set secondary timing and plane en_bit*/ |
aeec43da | 172 | setDisplayControl(1, (output & SEC_TP_MASK) >> SEC_TP_OFFSET); |
81dee67e SM |
173 | } |
174 | ||
8c11f5a2 | 175 | if (output & PNL_SEQ_USAGE) { |
81dee67e | 176 | /* set panel sequence */ |
aeec43da | 177 | swPanelPowerSequence((output & PNL_SEQ_MASK) >> PNL_SEQ_OFFSET, 4); |
81dee67e SM |
178 | } |
179 | ||
9ccc5f44 | 180 | if (output & DAC_USAGE) |
e80ef45d | 181 | setDAC((output & DAC_MASK) >> DAC_OFFSET); |
81dee67e | 182 | |
9ccc5f44 | 183 | if (output & DPMS_USAGE) |
81dee67e SM |
184 | ddk750_setDPMS((output & DPMS_MASK) >> DPMS_OFFSET); |
185 | } |