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