]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blame - drivers/staging/sm750fb/ddk750_chip.c
staging: sm750fb: fix line length coding style issues in ddk750_chip.c
[mirror_ubuntu-artful-kernel.git] / drivers / staging / sm750fb / ddk750_chip.c
CommitLineData
e074da3f 1#include <linux/kernel.h>
4cf26d85
MR
2#include <linux/sizes.h>
3
81dee67e
SM
4#include "ddk750_help.h"
5#include "ddk750_reg.h"
6#include "ddk750_chip.h"
7#include "ddk750_power.h"
81dee67e 8
603dd493
MR
9/* n / d + 1 / 2 = (2n + d) / 2d */
10#define roundedDiv(num, denom) ((2 * (num) + (denom)) / (2 * (denom)))
11#define MHz(x) ((x) * 1000000)
12
6fa7db83 13logical_chip_type_t getChipType(void)
81dee67e
SM
14{
15 unsigned short physicalID;
16 char physicalRev;
17 logical_chip_type_t chip;
18
5ee35ea7 19 physicalID = devId750; /* either 0x718 or 0x750 */
81dee67e
SM
20 physicalRev = revId750;
21
de99befd 22 if (physicalID == 0x718)
de99befd 23 chip = SM718;
9767fc51 24 else if (physicalID == 0x750) {
de99befd 25 chip = SM750;
81dee67e 26 /* SM750 and SM750LE are different in their revision ID only. */
9767fc51 27 if (physicalRev == SM750LE_REVISION_ID)
81dee67e 28 chip = SM750LE;
9767fc51 29 } else
de99befd 30 chip = SM_UNKNOWN;
81dee67e
SM
31
32 return chip;
33}
34
7092d76f 35static unsigned int get_mxclk_freq(void)
81dee67e 36{
7751e0e2
MR
37 unsigned int pll_reg;
38 unsigned int M, N, OD, POD;
39
82736d22 40 if (getChipType() == SM750LE)
81dee67e 41 return MHz(130);
81dee67e 42
7751e0e2 43 pll_reg = PEEK32(MXCLK_PLL_CTRL);
cdd5df64
MR
44 M = (pll_reg & PLL_CTRL_M_MASK) >> PLL_CTRL_M_SHIFT;
45 N = (pll_reg & PLL_CTRL_N_MASK) >> PLL_CTRL_M_SHIFT;
46 OD = (pll_reg & PLL_CTRL_OD_MASK) >> PLL_CTRL_OD_SHIFT;
47 POD = (pll_reg & PLL_CTRL_POD_MASK) >> PLL_CTRL_POD_SHIFT;
7751e0e2
MR
48
49 return DEFAULT_INPUT_CLOCK * M / N / (1 << OD) / (1 << POD);
81dee67e
SM
50}
51
81dee67e
SM
52/*
53 * This function set up the main chip clock.
54 *
55 * Input: Frequency to be set.
56 */
fb6f37a8 57static void setChipClock(unsigned int frequency)
81dee67e 58{
de99befd
RN
59 pll_value_t pll;
60 unsigned int ulActualMxClk;
cfac7d6a 61
de99befd
RN
62 /* Cheok_0509: For SM750LE, the chip clock is fixed. Nothing to set. */
63 if (getChipType() == SM750LE)
64 return;
81dee67e 65
59f08407 66 if (frequency) {
de99befd
RN
67 /*
68 * Set up PLL, a structure to hold the value to be set in clocks.
69 */
70 pll.inputFreq = DEFAULT_INPUT_CLOCK; /* Defined in CLOCK.H */
71 pll.clockType = MXCLK_PLL;
72
73 /*
46b7dd7c
MG
74 * Call calcPllValue() to fill the other fields of PLL structure.
75 * Sometime, the chip cannot set up the exact clock
76 * required by the User.
77 * Return value of calcPllValue gives the actual possible clock.
de99befd
RN
78 */
79 ulActualMxClk = calcPllValue(frequency, &pll);
80
81 /* Master Clock Control: MXCLK_PLL */
82 POKE32(MXCLK_PLL_CTRL, formatPllReg(&pll));
83 }
81dee67e
SM
84}
85
fb6f37a8 86static void setMemoryClock(unsigned int frequency)
81dee67e 87{
19aa2113 88 unsigned int reg, divisor;
cfac7d6a 89
f90416df
MG
90 /* Cheok_0509: For SM750LE, the memory clock is fixed.
91 * Nothing to set.
92 */
81dee67e
SM
93 if (getChipType() == SM750LE)
94 return;
cfac7d6a 95
59f08407 96 if (frequency) {
d943005a 97 /*
46b7dd7c
MG
98 * Set the frequency to the maximum frequency
99 * that the DDR Memory can take which is 336MHz.
d943005a 100 */
de99befd
RN
101 if (frequency > MHz(336))
102 frequency = MHz(336);
103
104 /* Calculate the divisor */
b02f9240 105 divisor = roundedDiv(get_mxclk_freq(), frequency);
de99befd
RN
106
107 /* Set the corresponding divisor in the register. */
6e8aa4a1 108 reg = PEEK32(CURRENT_GATE) & ~CURRENT_GATE_M2XCLK_MASK;
c107243b 109 switch (divisor) {
de99befd
RN
110 default:
111 case 1:
6e8aa4a1 112 reg |= CURRENT_GATE_M2XCLK_DIV_1;
de99befd
RN
113 break;
114 case 2:
6e8aa4a1 115 reg |= CURRENT_GATE_M2XCLK_DIV_2;
de99befd
RN
116 break;
117 case 3:
6e8aa4a1 118 reg |= CURRENT_GATE_M2XCLK_DIV_3;
de99befd
RN
119 break;
120 case 4:
6e8aa4a1 121 reg |= CURRENT_GATE_M2XCLK_DIV_4;
de99befd
RN
122 break;
123 }
124
19aa2113 125 setCurrentGate(reg);
de99befd 126 }
81dee67e
SM
127}
128
81dee67e
SM
129/*
130 * This function set up the master clock (MCLK).
131 *
132 * Input: Frequency to be set.
133 *
134 * NOTE:
135 * The maximum frequency the engine can run is 168MHz.
136 */
fb6f37a8 137static void setMasterClock(unsigned int frequency)
81dee67e 138{
19aa2113 139 unsigned int reg, divisor;
cfac7d6a 140
83d62831
MG
141 /* Cheok_0509: For SM750LE, the memory clock is fixed.
142 * Nothing to set.
143 */
81dee67e
SM
144 if (getChipType() == SM750LE)
145 return;
cfac7d6a 146
59f08407 147 if (frequency) {
de99befd
RN
148 /* Set the frequency to the maximum frequency that the SM750 engine can
149 run, which is about 190 MHz. */
150 if (frequency > MHz(190))
151 frequency = MHz(190);
152
153 /* Calculate the divisor */
b02f9240 154 divisor = roundedDiv(get_mxclk_freq(), frequency);
de99befd
RN
155
156 /* Set the corresponding divisor in the register. */
6e8aa4a1 157 reg = PEEK32(CURRENT_GATE) & ~CURRENT_GATE_MCLK_MASK;
c107243b 158 switch (divisor) {
de99befd
RN
159 default:
160 case 3:
6e8aa4a1 161 reg |= CURRENT_GATE_MCLK_DIV_3;
de99befd
RN
162 break;
163 case 4:
6e8aa4a1 164 reg |= CURRENT_GATE_MCLK_DIV_4;
de99befd
RN
165 break;
166 case 6:
6e8aa4a1 167 reg |= CURRENT_GATE_MCLK_DIV_6;
de99befd
RN
168 break;
169 case 8:
6e8aa4a1 170 reg |= CURRENT_GATE_MCLK_DIV_8;
de99befd
RN
171 break;
172 }
173
19aa2113 174 setCurrentGate(reg);
de99befd 175 }
81dee67e
SM
176}
177
6fa7db83 178unsigned int ddk750_getVMSize(void)
81dee67e
SM
179{
180 unsigned int reg;
181 unsigned int data;
182
183 /* sm750le only use 64 mb memory*/
82736d22 184 if (getChipType() == SM750LE)
4cf26d85 185 return SZ_64M;
81dee67e
SM
186
187 /* for 750,always use power mode0*/
188 reg = PEEK32(MODE0_GATE);
05e9d9ea 189 reg |= MODE0_GATE_GPIO;
c04051f5 190 POKE32(MODE0_GATE, reg);
81dee67e
SM
191
192 /* get frame buffer size from GPIO */
5538d5c8 193 reg = PEEK32(MISC_CTRL) & MISC_CTRL_LOCALMEM_SIZE_MASK;
c107243b 194 switch (reg) {
ae59c465 195 case MISC_CTRL_LOCALMEM_SIZE_8M:
4cf26d85 196 data = SZ_8M; break; /* 8 Mega byte */
ae59c465 197 case MISC_CTRL_LOCALMEM_SIZE_16M:
4cf26d85 198 data = SZ_16M; break; /* 16 Mega byte */
ae59c465 199 case MISC_CTRL_LOCALMEM_SIZE_32M:
4cf26d85 200 data = SZ_32M; break; /* 32 Mega byte */
ae59c465 201 case MISC_CTRL_LOCALMEM_SIZE_64M:
4cf26d85 202 data = SZ_64M; break; /* 64 Mega byte */
ae59c465 203 default:
e261e69e
AKC
204 data = 0;
205 break;
81dee67e
SM
206 }
207 return data;
81dee67e
SM
208}
209
f8da055a 210int ddk750_initHw(initchip_param_t *pInitParam)
81dee67e 211{
8bc728cf 212 unsigned int reg;
81dee67e 213
8332d94c 214 if (pInitParam->powerMode != 0)
81dee67e
SM
215 pInitParam->powerMode = 0;
216 setPowerMode(pInitParam->powerMode);
217
218 /* Enable display power gate & LOCALMEM power gate*/
8bc728cf 219 reg = PEEK32(CURRENT_GATE);
90946e52 220 reg |= (CURRENT_GATE_DISPLAY | CURRENT_GATE_LOCALMEM);
8bc728cf 221 setCurrentGate(reg);
81dee67e 222
82736d22 223 if (getChipType() != SM750LE) {
81dee67e 224 /* set panel pll and graphic mode via mmio_88 */
8bc728cf 225 reg = PEEK32(VGA_CONFIGURATION);
d9798143 226 reg |= (VGA_CONFIGURATION_PLL | VGA_CONFIGURATION_MODE);
8bc728cf 227 POKE32(VGA_CONFIGURATION, reg);
9767fc51 228 } else {
31296ba5 229#if defined(__i386__) || defined(__x86_64__)
81dee67e 230 /* set graphic mode via IO method */
c04051f5
HF
231 outb_p(0x88, 0x3d4);
232 outb_p(0x06, 0x3d5);
81dee67e
SM
233#endif
234 }
235
236 /* Set the Main Chip Clock */
237 setChipClock(MHz((unsigned int)pInitParam->chipClock));
238
239 /* Set up memory clock. */
240 setMemoryClock(MHz(pInitParam->memClock));
241
242 /* Set up master clock */
243 setMasterClock(MHz(pInitParam->masterClock));
244
245
246 /* Reset the memory controller. If the memory controller is not reset in SM750,
247 the system might hang when sw accesses the memory.
248 The memory should be resetted after changing the MXCLK.
249 */
9767fc51 250 if (pInitParam->resetMemory == 1) {
8bc728cf 251 reg = PEEK32(MISC_CTRL);
5372350b 252 reg &= ~MISC_CTRL_LOCALMEM_RESET;
8bc728cf 253 POKE32(MISC_CTRL, reg);
81dee67e 254
5372350b 255 reg |= MISC_CTRL_LOCALMEM_RESET;
8bc728cf 256 POKE32(MISC_CTRL, reg);
81dee67e
SM
257 }
258
9767fc51 259 if (pInitParam->setAllEngOff == 1) {
81dee67e
SM
260 enable2DEngine(0);
261
262 /* Disable Overlay, if a former application left it on */
8bc728cf 263 reg = PEEK32(VIDEO_DISPLAY_CTRL);
6fba39cf 264 reg &= ~DISPLAY_CTRL_PLANE;
8bc728cf 265 POKE32(VIDEO_DISPLAY_CTRL, reg);
81dee67e
SM
266
267 /* Disable video alpha, if a former application left it on */
8bc728cf 268 reg = PEEK32(VIDEO_ALPHA_DISPLAY_CTRL);
6fba39cf 269 reg &= ~DISPLAY_CTRL_PLANE;
8bc728cf 270 POKE32(VIDEO_ALPHA_DISPLAY_CTRL, reg);
81dee67e
SM
271
272 /* Disable alpha plane, if a former application left it on */
8bc728cf 273 reg = PEEK32(ALPHA_DISPLAY_CTRL);
6fba39cf 274 reg &= ~DISPLAY_CTRL_PLANE;
8bc728cf 275 POKE32(ALPHA_DISPLAY_CTRL, reg);
81dee67e 276
81dee67e 277 /* Disable DMA Channel, if a former application left it on */
8bc728cf 278 reg = PEEK32(DMA_ABORT_INTERRUPT);
0f23be70 279 reg |= DMA_ABORT_INTERRUPT_ABORT_1;
8bc728cf 280 POKE32(DMA_ABORT_INTERRUPT, reg);
81dee67e
SM
281
282 /* Disable DMA Power, if a former application left it on */
283 enableDMA(0);
284 }
285
286 /* We can add more initialization as needed. */
287
288 return 0;
289}
290
81dee67e
SM
291/*
292 monk liu @ 4/6/2011:
293 re-write the calculatePLL function of ddk750.
294 the original version function does not use some mathematics tricks and shortcut
295 when it doing the calculation of the best N,M,D combination
296 I think this version gives a little upgrade in speed
297
298 750 pll clock formular:
299 Request Clock = (Input Clock * M )/(N * X)
300
301 Input Clock = 14318181 hz
302 X = 2 power D
303 D ={0,1,2,3,4,5,6}
304 M = {1,...,255}
305 N = {2,...,15}
306*/
c04051f5 307unsigned int calcPllValue(unsigned int request_orig, pll_value_t *pll)
81dee67e 308{
46b7dd7c
MG
309 /* as sm750 register definition,
310 * N located in 2,15 and M located in 1,255
311 */
c04051f5 312 int N, M, X, d;
43ce0b53 313 int mini_diff;
c04051f5
HF
314 unsigned int RN, quo, rem, fl_quo;
315 unsigned int input, request;
316 unsigned int tmpClock, ret;
a61dc139 317 const int max_OD = 3;
f0e00da2 318 int max_d = 6;
81dee67e 319
9767fc51 320 if (getChipType() == SM750LE) {
de99befd
RN
321 /* SM750LE don't have prgrammable PLL and M/N values to work on.
322 Just return the requested clock. */
323 return request_orig;
324 }
81dee67e
SM
325
326 ret = 0;
43ce0b53 327 mini_diff = ~0;
81dee67e
SM
328 request = request_orig / 1000;
329 input = pll->inputFreq / 1000;
330
46b7dd7c
MG
331 /* for MXCLK register,
332 * no POD provided, so need be treated differently
333 */
a61dc139
MR
334 if (pll->clockType == MXCLK_PLL)
335 max_d = 3;
81dee67e 336
ce02a16a 337 for (N = 15; N > 1; N--) {
46b7dd7c
MG
338 /* RN will not exceed maximum long
339 * if @request <= 285 MHZ (for 32bit cpu)
340 */
81dee67e
SM
341 RN = N * request;
342 quo = RN / input;
343 rem = RN % input;/* rem always small than 14318181 */
6ab5b6d1 344 fl_quo = (rem * 10000 / input);
81dee67e 345
a61dc139
MR
346 for (d = max_d; d >= 0; d--) {
347 X = (1 << d);
f40917ea 348 M = quo * X;
81dee67e
SM
349 M += fl_quo * X / 10000;
350 /* round step */
07387cba 351 M += (fl_quo * X % 10000) > 5000 ? 1 : 0;
82736d22 352 if (M < 256 && M > 0) {
81dee67e 353 unsigned int diff;
40403c1b 354
6ab5b6d1 355 tmpClock = pll->inputFreq * M / N / X;
e074da3f 356 diff = abs(tmpClock - request_orig);
43ce0b53 357 if (diff < mini_diff) {
81dee67e
SM
358 pll->M = M;
359 pll->N = N;
a61dc139
MR
360 pll->POD = 0;
361 if (d > max_OD)
362 pll->POD = d - max_OD;
363 pll->OD = d - pll->POD;
43ce0b53 364 mini_diff = diff;
81dee67e
SM
365 ret = tmpClock;
366 }
367 }
368 }
369 }
81dee67e
SM
370 return ret;
371}
372
81dee67e
SM
373unsigned int formatPllReg(pll_value_t *pPLL)
374{
cdd5df64
MR
375#ifndef VALIDATION_CHIP
376 unsigned int POD = pPLL->POD;
377#endif
378 unsigned int OD = pPLL->OD;
379 unsigned int M = pPLL->M;
380 unsigned int N = pPLL->N;
375b4d42 381 unsigned int reg = 0;
81dee67e 382
0c4d85fc
MR
383 /*
384 * Note that all PLL's have the same format. Here, we just use
385 * Panel PLL parameter to work out the bit fields in the
386 * register. On returning a 32 bit number, the value can be
387 * applied to any PLL in the calling function.
388 */
cdd5df64 389 reg = PLL_CTRL_POWER |
81dee67e 390#ifndef VALIDATION_CHIP
cdd5df64 391 ((POD << PLL_CTRL_POD_SHIFT) & PLL_CTRL_POD_MASK) |
81dee67e 392#endif
cdd5df64
MR
393 ((OD << PLL_CTRL_OD_SHIFT) & PLL_CTRL_OD_MASK) |
394 ((N << PLL_CTRL_N_SHIFT) & PLL_CTRL_N_MASK) |
395 ((M << PLL_CTRL_M_SHIFT) & PLL_CTRL_M_MASK);
81dee67e 396
375b4d42 397 return reg;
81dee67e
SM
398}
399
400