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