1 // SPDX-License-Identifier: GPL-2.0 2 3 #include "ddk750_reg.h" 4 #include "ddk750_mode.h" 5 #include "ddk750_chip.h" 6 7 /* 8 * SM750LE only: 9 * This function takes care extra registers and bit fields required to set 10 * up a mode in SM750LE 11 * 12 * Explanation about Display Control register: 13 * HW only supports 7 predefined pixel clocks, and clock select is 14 * in bit 29:27 of Display Control register. 15 */ 16 static unsigned long displayControlAdjust_SM750LE(struct mode_parameter *pModeParam, 17 unsigned long dispControl) 18 { 19 unsigned long x, y; 20 21 x = pModeParam->horizontal_display_end; 22 y = pModeParam->vertical_display_end; 23 24 /* 25 * SM750LE has to set up the top-left and bottom-right 26 * registers as well. 27 * Note that normal SM750/SM718 only use those two register for 28 * auto-centering mode. 29 */ 30 poke32(CRT_AUTO_CENTERING_TL, 0); 31 32 poke32(CRT_AUTO_CENTERING_BR, 33 (((y - 1) << CRT_AUTO_CENTERING_BR_BOTTOM_SHIFT) & 34 CRT_AUTO_CENTERING_BR_BOTTOM_MASK) | 35 ((x - 1) & CRT_AUTO_CENTERING_BR_RIGHT_MASK)); 36 37 /* 38 * Assume common fields in dispControl have been properly set before 39 * calling this function. 40 * This function only sets the extra fields in dispControl. 41 */ 42 43 /* Clear bit 29:27 of display control register */ 44 dispControl &= ~CRT_DISPLAY_CTRL_CLK_MASK; 45 46 /* Set bit 29:27 of display control register for the right clock */ 47 /* Note that SM750LE only need to supported 7 resolutions. */ 48 if (x == 800 && y == 600) 49 dispControl |= CRT_DISPLAY_CTRL_CLK_PLL41; 50 else if (x == 1024 && y == 768) 51 dispControl |= CRT_DISPLAY_CTRL_CLK_PLL65; 52 else if (x == 1152 && y == 864) 53 dispControl |= CRT_DISPLAY_CTRL_CLK_PLL80; 54 else if (x == 1280 && y == 768) 55 dispControl |= CRT_DISPLAY_CTRL_CLK_PLL80; 56 else if (x == 1280 && y == 720) 57 dispControl |= CRT_DISPLAY_CTRL_CLK_PLL74; 58 else if (x == 1280 && y == 960) 59 dispControl |= CRT_DISPLAY_CTRL_CLK_PLL108; 60 else if (x == 1280 && y == 1024) 61 dispControl |= CRT_DISPLAY_CTRL_CLK_PLL108; 62 else /* default to VGA clock */ 63 dispControl |= CRT_DISPLAY_CTRL_CLK_PLL25; 64 65 /* Set bit 25:24 of display controller */ 66 dispControl |= (CRT_DISPLAY_CTRL_CRTSELECT | CRT_DISPLAY_CTRL_RGBBIT); 67 68 /* Set bit 14 of display controller */ 69 dispControl |= DISPLAY_CTRL_CLOCK_PHASE; 70 71 poke32(CRT_DISPLAY_CTRL, dispControl); 72 73 return dispControl; 74 } 75 76 /* only timing related registers will be programed */ 77 static int programModeRegisters(struct mode_parameter *pModeParam, 78 struct pll_value *pll) 79 { 80 int ret = 0; 81 int cnt = 0; 82 unsigned int tmp, reg; 83 84 if (pll->clockType == SECONDARY_PLL) { 85 /* programe secondary pixel clock */ 86 poke32(CRT_PLL_CTRL, sm750_format_pll_reg(pll)); 87 88 tmp = ((pModeParam->horizontal_total - 1) << 89 CRT_HORIZONTAL_TOTAL_TOTAL_SHIFT) & 90 CRT_HORIZONTAL_TOTAL_TOTAL_MASK; 91 tmp |= (pModeParam->horizontal_display_end - 1) & 92 CRT_HORIZONTAL_TOTAL_DISPLAY_END_MASK; 93 94 poke32(CRT_HORIZONTAL_TOTAL, tmp); 95 96 tmp = (pModeParam->horizontal_sync_width << 97 CRT_HORIZONTAL_SYNC_WIDTH_SHIFT) & 98 CRT_HORIZONTAL_SYNC_WIDTH_MASK; 99 tmp |= (pModeParam->horizontal_sync_start - 1) & 100 CRT_HORIZONTAL_SYNC_START_MASK; 101 102 poke32(CRT_HORIZONTAL_SYNC, tmp); 103 104 tmp = ((pModeParam->vertical_total - 1) << 105 CRT_VERTICAL_TOTAL_TOTAL_SHIFT) & 106 CRT_VERTICAL_TOTAL_TOTAL_MASK; 107 tmp |= (pModeParam->vertical_display_end - 1) & 108 CRT_VERTICAL_TOTAL_DISPLAY_END_MASK; 109 110 poke32(CRT_VERTICAL_TOTAL, tmp); 111 112 tmp = ((pModeParam->vertical_sync_height << 113 CRT_VERTICAL_SYNC_HEIGHT_SHIFT)) & 114 CRT_VERTICAL_SYNC_HEIGHT_MASK; 115 tmp |= (pModeParam->vertical_sync_start - 1) & 116 CRT_VERTICAL_SYNC_START_MASK; 117 118 poke32(CRT_VERTICAL_SYNC, tmp); 119 120 tmp = DISPLAY_CTRL_TIMING | DISPLAY_CTRL_PLANE; 121 if (pModeParam->vertical_sync_polarity) 122 tmp |= DISPLAY_CTRL_VSYNC_PHASE; 123 if (pModeParam->horizontal_sync_polarity) 124 tmp |= DISPLAY_CTRL_HSYNC_PHASE; 125 126 if (sm750_get_chip_type() == SM750LE) { 127 displayControlAdjust_SM750LE(pModeParam, tmp); 128 } else { 129 reg = peek32(CRT_DISPLAY_CTRL) & 130 ~(DISPLAY_CTRL_VSYNC_PHASE | 131 DISPLAY_CTRL_HSYNC_PHASE | 132 DISPLAY_CTRL_TIMING | DISPLAY_CTRL_PLANE); 133 134 poke32(CRT_DISPLAY_CTRL, tmp | reg); 135 } 136 137 } else if (pll->clockType == PRIMARY_PLL) { 138 unsigned int reserved; 139 140 poke32(PANEL_PLL_CTRL, sm750_format_pll_reg(pll)); 141 142 reg = ((pModeParam->horizontal_total - 1) << 143 PANEL_HORIZONTAL_TOTAL_TOTAL_SHIFT) & 144 PANEL_HORIZONTAL_TOTAL_TOTAL_MASK; 145 reg |= ((pModeParam->horizontal_display_end - 1) & 146 PANEL_HORIZONTAL_TOTAL_DISPLAY_END_MASK); 147 poke32(PANEL_HORIZONTAL_TOTAL, reg); 148 149 poke32(PANEL_HORIZONTAL_SYNC, 150 ((pModeParam->horizontal_sync_width << 151 PANEL_HORIZONTAL_SYNC_WIDTH_SHIFT) & 152 PANEL_HORIZONTAL_SYNC_WIDTH_MASK) | 153 ((pModeParam->horizontal_sync_start - 1) & 154 PANEL_HORIZONTAL_SYNC_START_MASK)); 155 156 poke32(PANEL_VERTICAL_TOTAL, 157 (((pModeParam->vertical_total - 1) << 158 PANEL_VERTICAL_TOTAL_TOTAL_SHIFT) & 159 PANEL_VERTICAL_TOTAL_TOTAL_MASK) | 160 ((pModeParam->vertical_display_end - 1) & 161 PANEL_VERTICAL_TOTAL_DISPLAY_END_MASK)); 162 163 poke32(PANEL_VERTICAL_SYNC, 164 ((pModeParam->vertical_sync_height << 165 PANEL_VERTICAL_SYNC_HEIGHT_SHIFT) & 166 PANEL_VERTICAL_SYNC_HEIGHT_MASK) | 167 ((pModeParam->vertical_sync_start - 1) & 168 PANEL_VERTICAL_SYNC_START_MASK)); 169 170 tmp = DISPLAY_CTRL_TIMING | DISPLAY_CTRL_PLANE; 171 if (pModeParam->vertical_sync_polarity) 172 tmp |= DISPLAY_CTRL_VSYNC_PHASE; 173 if (pModeParam->horizontal_sync_polarity) 174 tmp |= DISPLAY_CTRL_HSYNC_PHASE; 175 if (pModeParam->clock_phase_polarity) 176 tmp |= DISPLAY_CTRL_CLOCK_PHASE; 177 178 reserved = PANEL_DISPLAY_CTRL_RESERVED_MASK | 179 PANEL_DISPLAY_CTRL_VSYNC; 180 181 reg = (peek32(PANEL_DISPLAY_CTRL) & ~reserved) & 182 ~(DISPLAY_CTRL_CLOCK_PHASE | DISPLAY_CTRL_VSYNC_PHASE | 183 DISPLAY_CTRL_HSYNC_PHASE | DISPLAY_CTRL_TIMING | 184 DISPLAY_CTRL_PLANE); 185 186 /* 187 * May a hardware bug or just my test chip (not confirmed). 188 * PANEL_DISPLAY_CTRL register seems requiring few writes 189 * before a value can be successfully written in. 190 * Added some masks to mask out the reserved bits. 191 * Note: This problem happens by design. The hardware will wait 192 * for the next vertical sync to turn on/off the plane. 193 */ 194 poke32(PANEL_DISPLAY_CTRL, tmp | reg); 195 196 while ((peek32(PANEL_DISPLAY_CTRL) & ~reserved) != 197 (tmp | reg)) { 198 cnt++; 199 if (cnt > 1000) 200 break; 201 poke32(PANEL_DISPLAY_CTRL, tmp | reg); 202 } 203 } else { 204 ret = -1; 205 } 206 return ret; 207 } 208 209 int ddk750_setModeTiming(struct mode_parameter *parm, enum clock_type clock) 210 { 211 struct pll_value pll; 212 unsigned int uiActualPixelClk; 213 214 pll.inputFreq = DEFAULT_INPUT_CLOCK; 215 pll.clockType = clock; 216 217 uiActualPixelClk = sm750_calc_pll_value(parm->pixel_clock, &pll); 218 if (sm750_get_chip_type() == SM750LE) { 219 /* set graphic mode via IO method */ 220 outb_p(0x88, 0x3d4); 221 outb_p(0x06, 0x3d5); 222 } 223 programModeRegisters(parm, &pll); 224 return 0; 225 } 226