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