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