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