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