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
1
2 #include "ddk750_reg.h"
3 #include "ddk750_mode.h"
4 #include "ddk750_chip.h"
5
6 /*
7  * SM750LE only:
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  */
15 static unsigned long displayControlAdjust_SM750LE(struct mode_parameter *pModeParam,
16                                                   unsigned long dispControl)
17 {
18         unsigned long x, y;
19
20         x = pModeParam->horizontal_display_end;
21         y = pModeParam->vertical_display_end;
22
23         /*
24          * SM750LE has to set up the top-left and bottom-right
25          * registers as well.
26          * Note that normal SM750/SM718 only use those two register for
27          * auto-centering mode.
28          */
29         poke32(CRT_AUTO_CENTERING_TL, 0);
30
31         poke32(CRT_AUTO_CENTERING_BR,
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));
35
36         /*
37          * Assume common fields in dispControl have been properly set before
38          * calling this function.
39          * This function only sets the extra fields in dispControl.
40          */
41
42         /* Clear bit 29:27 of display control register */
43         dispControl &= ~CRT_DISPLAY_CTRL_CLK_MASK;
44
45         /* Set bit 29:27 of display control register for the right clock */
46         /* Note that SM750LE only need to supported 7 resolutions. */
47         if (x == 800 && y == 600)
48                 dispControl |= CRT_DISPLAY_CTRL_CLK_PLL41;
49         else if (x == 1024 && y == 768)
50                 dispControl |= CRT_DISPLAY_CTRL_CLK_PLL65;
51         else if (x == 1152 && y == 864)
52                 dispControl |= CRT_DISPLAY_CTRL_CLK_PLL80;
53         else if (x == 1280 && y == 768)
54                 dispControl |= CRT_DISPLAY_CTRL_CLK_PLL80;
55         else if (x == 1280 && y == 720)
56                 dispControl |= CRT_DISPLAY_CTRL_CLK_PLL74;
57         else if (x == 1280 && y == 960)
58                 dispControl |= CRT_DISPLAY_CTRL_CLK_PLL108;
59         else if (x == 1280 && y == 1024)
60                 dispControl |= CRT_DISPLAY_CTRL_CLK_PLL108;
61         else /* default to VGA clock */
62                 dispControl |= CRT_DISPLAY_CTRL_CLK_PLL25;
63
64         /* Set bit 25:24 of display controller */
65         dispControl |= (CRT_DISPLAY_CTRL_CRTSELECT | CRT_DISPLAY_CTRL_RGBBIT);
66
67         /* Set bit 14 of display controller */
68         dispControl |= DISPLAY_CTRL_CLOCK_PHASE;
69
70         poke32(CRT_DISPLAY_CTRL, dispControl);
71
72         return dispControl;
73 }
74
75 /* only timing related registers will be  programed */
76 static int programModeRegisters(struct mode_parameter *pModeParam,
77                                 struct pll_value *pll)
78 {
79         int ret = 0;
80         int cnt = 0;
81         unsigned int tmp, reg;
82
83         if (pll->clockType == SECONDARY_PLL) {
84                 /* programe secondary pixel clock */
85                 poke32(CRT_PLL_CTRL, sm750_format_pll_reg(pll));
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);
118
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;
124
125                 if (sm750_get_chip_type() == SM750LE) {
126                         displayControlAdjust_SM750LE(pModeParam, tmp);
127                 } else {
128                         reg = peek32(CRT_DISPLAY_CTRL) &
129                                 ~(DISPLAY_CTRL_VSYNC_PHASE |
130                                   DISPLAY_CTRL_HSYNC_PHASE |
131                                   DISPLAY_CTRL_TIMING | DISPLAY_CTRL_PLANE);
132
133                          poke32(CRT_DISPLAY_CTRL, tmp | reg);
134                 }
135
136         } else if (pll->clockType == PRIMARY_PLL) {
137                 unsigned int reserved;
138
139                 poke32(PANEL_PLL_CTRL, sm750_format_pll_reg(pll));
140
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);
146                 poke32(PANEL_HORIZONTAL_TOTAL, reg);
147
148                 poke32(PANEL_HORIZONTAL_SYNC,
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));
154
155                 poke32(PANEL_VERTICAL_TOTAL,
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));
161
162                 poke32(PANEL_VERTICAL_SYNC,
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));
168
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;
176
177                 reserved = PANEL_DISPLAY_CTRL_RESERVED_MASK |
178                         PANEL_DISPLAY_CTRL_VSYNC;
179
180                 reg = (peek32(PANEL_DISPLAY_CTRL) & ~reserved) &
181                         ~(DISPLAY_CTRL_CLOCK_PHASE | DISPLAY_CTRL_VSYNC_PHASE |
182                           DISPLAY_CTRL_HSYNC_PHASE | DISPLAY_CTRL_TIMING |
183                           DISPLAY_CTRL_PLANE);
184
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                  */
193                 poke32(PANEL_DISPLAY_CTRL, tmp | reg);
194
195                 while ((peek32(PANEL_DISPLAY_CTRL) & ~reserved) !=
196                         (tmp | reg)) {
197                         cnt++;
198                         if (cnt > 1000)
199                                 break;
200                         poke32(PANEL_DISPLAY_CTRL, tmp | reg);
201                 }
202         } else {
203                 ret = -1;
204         }
205         return ret;
206 }
207
208 int ddk750_setModeTiming(struct mode_parameter *parm, clock_type_t clock)
209 {
210         struct pll_value pll;
211         unsigned int uiActualPixelClk;
212
213         pll.inputFreq = DEFAULT_INPUT_CLOCK;
214         pll.clockType = clock;
215
216         uiActualPixelClk = sm750_calc_pll_value(parm->pixel_clock, &pll);
217         if (sm750_get_chip_type() == SM750LE) {
218                 /* set graphic mode via IO method */
219                 outb_p(0x88, 0x3d4);
220                 outb_p(0x06, 0x3d5);
221         }
222         programModeRegisters(parm, &pll);
223         return 0;
224 }