]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blob - drivers/staging/sm750fb/ddk750_chip.c
drivers: staging: sm750fb: Fix "'foo * bar' should be 'foo *bar'" errors
[mirror_ubuntu-bionic-kernel.git] / drivers / staging / sm750fb / ddk750_chip.c
1 #include "ddk750_help.h"
2 #include "ddk750_reg.h"
3 #include "ddk750_chip.h"
4 #include "ddk750_power.h"
5 typedef struct _pllcalparam {
6 unsigned char power;/* d : 0~ 6*/
7 unsigned char pod;
8 unsigned char od;
9 unsigned char value;/* value of 2 power d (2^d) */
10 }
11 pllcalparam;
12
13
14 logical_chip_type_t getChipType(void)
15 {
16 unsigned short physicalID;
17 char physicalRev;
18 logical_chip_type_t chip;
19
20 physicalID = devId750; /* either 0x718 or 0x750 */
21 physicalRev = revId750;
22
23 if (physicalID == 0x718)
24 chip = SM718;
25 else if (physicalID == 0x750) {
26 chip = SM750;
27 /* SM750 and SM750LE are different in their revision ID only. */
28 if (physicalRev == SM750LE_REVISION_ID)
29 chip = SM750LE;
30 } else
31 chip = SM_UNKNOWN;
32
33 return chip;
34 }
35
36
37 inline unsigned int twoToPowerOfx(unsigned long x)
38 {
39 unsigned long i;
40 unsigned long result = 1;
41
42 for (i = 1; i <= x; i++)
43 result *= 2;
44 return result;
45 }
46
47 inline unsigned int calcPLL(pll_value_t *pPLL)
48 {
49 return (pPLL->inputFreq * pPLL->M / pPLL->N / twoToPowerOfx(pPLL->OD) / twoToPowerOfx(pPLL->POD));
50 }
51
52 unsigned int getPllValue(clock_type_t clockType, pll_value_t *pPLL)
53 {
54 unsigned int ulPllReg = 0;
55
56 pPLL->inputFreq = DEFAULT_INPUT_CLOCK;
57 pPLL->clockType = clockType;
58
59 switch (clockType) {
60 case MXCLK_PLL:
61 ulPllReg = PEEK32(MXCLK_PLL_CTRL);
62 break;
63 case PRIMARY_PLL:
64 ulPllReg = PEEK32(PANEL_PLL_CTRL);
65 break;
66 case SECONDARY_PLL:
67 ulPllReg = PEEK32(CRT_PLL_CTRL);
68 break;
69 case VGA0_PLL:
70 ulPllReg = PEEK32(VGA_PLL0_CTRL);
71 break;
72 case VGA1_PLL:
73 ulPllReg = PEEK32(VGA_PLL1_CTRL);
74 break;
75 }
76
77 pPLL->M = FIELD_GET(ulPllReg, PANEL_PLL_CTRL, M);
78 pPLL->N = FIELD_GET(ulPllReg, PANEL_PLL_CTRL, N);
79 pPLL->OD = FIELD_GET(ulPllReg, PANEL_PLL_CTRL, OD);
80 pPLL->POD = FIELD_GET(ulPllReg, PANEL_PLL_CTRL, POD);
81
82 return calcPLL(pPLL);
83 }
84
85
86 unsigned int getChipClock(void)
87 {
88 pll_value_t pll;
89 #if 1
90 if (getChipType() == SM750LE)
91 return MHz(130);
92 #endif
93
94 return getPllValue(MXCLK_PLL, &pll);
95 }
96
97
98 /*
99 * This function set up the main chip clock.
100 *
101 * Input: Frequency to be set.
102 */
103 void setChipClock(unsigned int frequency)
104 {
105 pll_value_t pll;
106 unsigned int ulActualMxClk;
107 #if 1
108 /* Cheok_0509: For SM750LE, the chip clock is fixed. Nothing to set. */
109 if (getChipType() == SM750LE)
110 return;
111 #endif
112
113 if (frequency) {
114 /*
115 * Set up PLL, a structure to hold the value to be set in clocks.
116 */
117 pll.inputFreq = DEFAULT_INPUT_CLOCK; /* Defined in CLOCK.H */
118 pll.clockType = MXCLK_PLL;
119
120 /*
121 * Call calcPllValue() to fill up the other fields for PLL structure.
122 * Sometime, the chip cannot set up the exact clock required by User.
123 * Return value from calcPllValue() gives the actual possible clock.
124 */
125 ulActualMxClk = calcPllValue(frequency, &pll);
126
127 /* Master Clock Control: MXCLK_PLL */
128 POKE32(MXCLK_PLL_CTRL, formatPllReg(&pll));
129 }
130 }
131
132
133
134 void setMemoryClock(unsigned int frequency)
135 {
136 unsigned int ulReg, divisor;
137 #if 1
138 /* Cheok_0509: For SM750LE, the memory clock is fixed. Nothing to set. */
139 if (getChipType() == SM750LE)
140 return;
141 #endif
142 if (frequency) {
143 /* Set the frequency to the maximum frequency that the DDR Memory can take
144 which is 336MHz. */
145 if (frequency > MHz(336))
146 frequency = MHz(336);
147
148 /* Calculate the divisor */
149 divisor = (unsigned int) roundedDiv(getChipClock(), frequency);
150
151 /* Set the corresponding divisor in the register. */
152 ulReg = PEEK32(CURRENT_GATE);
153 switch (divisor) {
154 default:
155 case 1:
156 ulReg = FIELD_SET(ulReg, CURRENT_GATE, M2XCLK, DIV_1);
157 break;
158 case 2:
159 ulReg = FIELD_SET(ulReg, CURRENT_GATE, M2XCLK, DIV_2);
160 break;
161 case 3:
162 ulReg = FIELD_SET(ulReg, CURRENT_GATE, M2XCLK, DIV_3);
163 break;
164 case 4:
165 ulReg = FIELD_SET(ulReg, CURRENT_GATE, M2XCLK, DIV_4);
166 break;
167 }
168
169 setCurrentGate(ulReg);
170 }
171 }
172
173
174 /*
175 * This function set up the master clock (MCLK).
176 *
177 * Input: Frequency to be set.
178 *
179 * NOTE:
180 * The maximum frequency the engine can run is 168MHz.
181 */
182 void setMasterClock(unsigned int frequency)
183 {
184 unsigned int ulReg, divisor;
185 #if 1
186 /* Cheok_0509: For SM750LE, the memory clock is fixed. Nothing to set. */
187 if (getChipType() == SM750LE)
188 return;
189 #endif
190 if (frequency) {
191 /* Set the frequency to the maximum frequency that the SM750 engine can
192 run, which is about 190 MHz. */
193 if (frequency > MHz(190))
194 frequency = MHz(190);
195
196 /* Calculate the divisor */
197 divisor = (unsigned int) roundedDiv(getChipClock(), frequency);
198
199 /* Set the corresponding divisor in the register. */
200 ulReg = PEEK32(CURRENT_GATE);
201 switch (divisor) {
202 default:
203 case 3:
204 ulReg = FIELD_SET(ulReg, CURRENT_GATE, MCLK, DIV_3);
205 break;
206 case 4:
207 ulReg = FIELD_SET(ulReg, CURRENT_GATE, MCLK, DIV_4);
208 break;
209 case 6:
210 ulReg = FIELD_SET(ulReg, CURRENT_GATE, MCLK, DIV_6);
211 break;
212 case 8:
213 ulReg = FIELD_SET(ulReg, CURRENT_GATE, MCLK, DIV_8);
214 break;
215 }
216
217 setCurrentGate(ulReg);
218 }
219 }
220
221
222 unsigned int ddk750_getVMSize(void)
223 {
224 unsigned int reg;
225 unsigned int data;
226
227 /* sm750le only use 64 mb memory*/
228 if (getChipType() == SM750LE)
229 return MB(64);
230
231 /* for 750,always use power mode0*/
232 reg = PEEK32(MODE0_GATE);
233 reg = FIELD_SET(reg, MODE0_GATE, GPIO, ON);
234 POKE32(MODE0_GATE, reg);
235
236 /* get frame buffer size from GPIO */
237 reg = FIELD_GET(PEEK32(MISC_CTRL), MISC_CTRL, LOCALMEM_SIZE);
238 switch (reg) {
239 case MISC_CTRL_LOCALMEM_SIZE_8M:
240 data = MB(8); break; /* 8 Mega byte */
241 case MISC_CTRL_LOCALMEM_SIZE_16M:
242 data = MB(16); break; /* 16 Mega byte */
243 case MISC_CTRL_LOCALMEM_SIZE_32M:
244 data = MB(32); break; /* 32 Mega byte */
245 case MISC_CTRL_LOCALMEM_SIZE_64M:
246 data = MB(64); break; /* 64 Mega byte */
247 default:
248 data = 0;
249 break;
250 }
251 return data;
252
253 }
254
255 int ddk750_initHw(initchip_param_t *pInitParam)
256 {
257
258 unsigned int ulReg;
259 #if 0
260 /* move the code to map regiter function. */
261 if (getChipType() == SM718) {
262 /* turn on big endian bit*/
263 ulReg = PEEK32(0x74);
264 /* now consider register definition in a big endian pattern*/
265 POKE32(0x74, ulReg|0x80000000);
266 }
267
268 #endif
269
270
271 if (pInitParam->powerMode != 0 )
272 pInitParam->powerMode = 0;
273 setPowerMode(pInitParam->powerMode);
274
275 /* Enable display power gate & LOCALMEM power gate*/
276 ulReg = PEEK32(CURRENT_GATE);
277 ulReg = FIELD_SET(ulReg, CURRENT_GATE, DISPLAY, ON);
278 ulReg = FIELD_SET(ulReg, CURRENT_GATE, LOCALMEM, ON);
279 setCurrentGate(ulReg);
280
281 if (getChipType() != SM750LE) {
282 /* set panel pll and graphic mode via mmio_88 */
283 ulReg = PEEK32(VGA_CONFIGURATION);
284 ulReg = FIELD_SET(ulReg, VGA_CONFIGURATION, PLL, PANEL);
285 ulReg = FIELD_SET(ulReg, VGA_CONFIGURATION, MODE, GRAPHIC);
286 POKE32(VGA_CONFIGURATION, ulReg);
287 } else {
288 #if defined(__i386__) || defined(__x86_64__)
289 /* set graphic mode via IO method */
290 outb_p(0x88, 0x3d4);
291 outb_p(0x06, 0x3d5);
292 #endif
293 }
294
295 /* Set the Main Chip Clock */
296 setChipClock(MHz((unsigned int)pInitParam->chipClock));
297
298 /* Set up memory clock. */
299 setMemoryClock(MHz(pInitParam->memClock));
300
301 /* Set up master clock */
302 setMasterClock(MHz(pInitParam->masterClock));
303
304
305 /* Reset the memory controller. If the memory controller is not reset in SM750,
306 the system might hang when sw accesses the memory.
307 The memory should be resetted after changing the MXCLK.
308 */
309 if (pInitParam->resetMemory == 1) {
310 ulReg = PEEK32(MISC_CTRL);
311 ulReg = FIELD_SET(ulReg, MISC_CTRL, LOCALMEM_RESET, RESET);
312 POKE32(MISC_CTRL, ulReg);
313
314 ulReg = FIELD_SET(ulReg, MISC_CTRL, LOCALMEM_RESET, NORMAL);
315 POKE32(MISC_CTRL, ulReg);
316 }
317
318 if (pInitParam->setAllEngOff == 1) {
319 enable2DEngine(0);
320
321 /* Disable Overlay, if a former application left it on */
322 ulReg = PEEK32(VIDEO_DISPLAY_CTRL);
323 ulReg = FIELD_SET(ulReg, VIDEO_DISPLAY_CTRL, PLANE, DISABLE);
324 POKE32(VIDEO_DISPLAY_CTRL, ulReg);
325
326 /* Disable video alpha, if a former application left it on */
327 ulReg = PEEK32(VIDEO_ALPHA_DISPLAY_CTRL);
328 ulReg = FIELD_SET(ulReg, VIDEO_ALPHA_DISPLAY_CTRL, PLANE, DISABLE);
329 POKE32(VIDEO_ALPHA_DISPLAY_CTRL, ulReg);
330
331 /* Disable alpha plane, if a former application left it on */
332 ulReg = PEEK32(ALPHA_DISPLAY_CTRL);
333 ulReg = FIELD_SET(ulReg, ALPHA_DISPLAY_CTRL, PLANE, DISABLE);
334 POKE32(ALPHA_DISPLAY_CTRL, ulReg);
335
336 #if 0
337 /* Disable LCD hardware cursor, if a former application left it on */
338 ulReg = PEEK32(PANEL_HWC_ADDRESS);
339 ulReg = FIELD_SET(ulReg, PANEL_HWC_ADDRESS, ENABLE, DISABLE);
340 POKE32(PANEL_HWC_ADDRESS, ulReg);
341
342 /* Disable CRT hardware cursor, if a former application left it on */
343 ulReg = PEEK32(CRT_HWC_ADDRESS);
344 ulReg = FIELD_SET(ulReg, CRT_HWC_ADDRESS, ENABLE, DISABLE);
345 POKE32(CRT_HWC_ADDRESS, ulReg);
346
347 /* Disable ZV Port 0, if a former application left it on */
348 ulReg = PEEK32(ZV0_CAPTURE_CTRL);
349 ulReg = FIELD_SET(ulReg, ZV0_CAPTURE_CTRL, CAP, DISABLE);
350 POKE32(ZV0_CAPTURE_CTRL, ulReg);
351
352 /* Disable ZV Port 1, if a former application left it on */
353 ulReg = PEEK32(ZV1_CAPTURE_CTRL);
354 ulReg = FIELD_SET(ulReg, ZV1_CAPTURE_CTRL, CAP, DISABLE);
355 POKE32(ZV1_CAPTURE_CTRL, ulReg);
356
357 /* Disable ZV Port Power, if a former application left it on */
358 enableZVPort(0);
359 /* Disable DMA Channel, if a former application left it on */
360 ulReg = PEEK32(DMA_ABORT_INTERRUPT);
361 ulReg = FIELD_SET(ulReg, DMA_ABORT_INTERRUPT, ABORT_1, ABORT);
362 POKE32(DMA_ABORT_INTERRUPT, ulReg);
363
364 /* Disable i2c */
365 enableI2C(0);
366 #endif
367 /* Disable DMA Channel, if a former application left it on */
368 ulReg = PEEK32(DMA_ABORT_INTERRUPT);
369 ulReg = FIELD_SET(ulReg, DMA_ABORT_INTERRUPT, ABORT_1, ABORT);
370 POKE32(DMA_ABORT_INTERRUPT, ulReg);
371
372 /* Disable DMA Power, if a former application left it on */
373 enableDMA(0);
374 }
375
376 /* We can add more initialization as needed. */
377
378 return 0;
379 }
380
381 #if 0
382
383 unsigned int absDiff(unsigned int a, unsigned int b)
384 {
385 if (a > b)
386 return(a - b);
387 else
388 return(b - a);
389 }
390
391 #endif
392 /*
393 monk liu @ 4/6/2011:
394 re-write the calculatePLL function of ddk750.
395 the original version function does not use some mathematics tricks and shortcut
396 when it doing the calculation of the best N,M,D combination
397 I think this version gives a little upgrade in speed
398
399 750 pll clock formular:
400 Request Clock = (Input Clock * M )/(N * X)
401
402 Input Clock = 14318181 hz
403 X = 2 power D
404 D ={0,1,2,3,4,5,6}
405 M = {1,...,255}
406 N = {2,...,15}
407 */
408 unsigned int calcPllValue(unsigned int request_orig, pll_value_t *pll)
409 {
410 /* used for primary and secondary channel pixel clock pll */
411 static pllcalparam xparm_PIXEL[] = {
412 /* 2^0 = 1*/ {0, 0, 0, 1},
413 /* 2^ 1 =2*/ {1, 0, 1, 2},
414 /* 2^ 2 = 4*/ {2, 0, 2, 4},
415 {3, 0, 3, 8},
416 {4, 1, 3, 16},
417 {5, 2, 3, 32},
418 /* 2^6 = 64 */ {6, 3, 3, 64},
419 };
420
421 /* used for MXCLK (chip clock) */
422 static pllcalparam xparm_MXCLK[] = {
423 /* 2^0 = 1*/ {0, 0, 0, 1},
424 /* 2^ 1 =2*/ {1, 0, 1, 2},
425 /* 2^ 2 = 4*/ {2, 0, 2, 4},
426 {3, 0, 3, 8},
427 };
428
429 /* as sm750 register definition, N located in 2,15 and M located in 1,255 */
430 int N, M, X, d;
431 int xcnt;
432 int miniDiff;
433 unsigned int RN, quo, rem, fl_quo;
434 unsigned int input, request;
435 unsigned int tmpClock, ret;
436 pllcalparam *xparm;
437
438 #if 1
439 if (getChipType() == SM750LE) {
440 /* SM750LE don't have prgrammable PLL and M/N values to work on.
441 Just return the requested clock. */
442 return request_orig;
443 }
444 #endif
445
446 ret = 0;
447 miniDiff = ~0;
448 request = request_orig / 1000;
449 input = pll->inputFreq / 1000;
450
451 /* for MXCLK register , no POD provided, so need be treated differently */
452
453 if (pll->clockType != MXCLK_PLL) {
454 xparm = &xparm_PIXEL[0];
455 xcnt = sizeof(xparm_PIXEL)/sizeof(xparm_PIXEL[0]);
456 } else {
457 xparm = &xparm_MXCLK[0];
458 xcnt = sizeof(xparm_MXCLK)/sizeof(xparm_MXCLK[0]);
459 }
460
461
462 for (N = 15; N > 1; N--) {
463 /* RN will not exceed maximum long if @request <= 285 MHZ (for 32bit cpu) */
464 RN = N * request;
465 quo = RN / input;
466 rem = RN % input;/* rem always small than 14318181 */
467 fl_quo = (rem * 10000 /input);
468
469 for (d = xcnt - 1; d >= 0; d--) {
470 X = xparm[d].value;
471 M = quo*X;
472 M += fl_quo * X / 10000;
473 /* round step */
474 M += (fl_quo*X % 10000)>5000?1:0;
475 if (M < 256 && M > 0) {
476 unsigned int diff;
477 tmpClock = pll->inputFreq *M / N / X;
478 diff = absDiff(tmpClock, request_orig);
479 if (diff < miniDiff) {
480 pll->M = M;
481 pll->N = N;
482 pll->OD = xparm[d].od;
483 pll->POD = xparm[d].pod;
484 miniDiff = diff;
485 ret = tmpClock;
486 }
487 }
488 }
489 }
490 return ret;
491 }
492
493 unsigned int calcPllValue2(
494 unsigned int ulRequestClk, /* Required pixel clock in Hz unit */
495 pll_value_t *pPLL /* Structure to hold the value to be set in PLL */
496 )
497 {
498 unsigned int M, N, OD, POD = 0, diff, pllClk, odPower, podPower;
499 unsigned int bestDiff = 0xffffffff; /* biggest 32 bit unsigned number */
500 unsigned int ret;
501 /* Init PLL structure to know states */
502 pPLL->M = 0;
503 pPLL->N = 0;
504 pPLL->OD = 0;
505 pPLL->POD = 0;
506
507 /* Sanity check: None at the moment */
508
509 /* Convert everything in Khz range in order to avoid calculation overflow */
510 pPLL->inputFreq /= 1000;
511 ulRequestClk /= 1000;
512
513 #ifndef VALIDATION_CHIP
514 /* The maximum of post divider is 8. */
515 for (POD = 0; POD <= 3; POD++)
516 #endif
517 {
518
519 #ifndef VALIDATION_CHIP
520 /* MXCLK_PLL does not have post divider. */
521 if ((POD > 0) && (pPLL->clockType == MXCLK_PLL))
522 break;
523 #endif
524
525 /* Work out 2 to the power of POD */
526 podPower = twoToPowerOfx(POD);
527
528 /* OD has only 2 bits [15:14] and its value must between 0 to 3 */
529 for (OD = 0; OD <= 3; OD++) {
530 /* Work out 2 to the power of OD */
531 odPower = twoToPowerOfx(OD);
532
533 #ifdef VALIDATION_CHIP
534 if (odPower > 4)
535 podPower = 4;
536 else
537 podPower = odPower;
538 #endif
539
540 /* N has 4 bits [11:8] and its value must between 2 and 15.
541 The N == 1 will behave differently --> Result is not correct. */
542 for (N = 2; N <= 15; N++) {
543 /* The formula for PLL is ulRequestClk = inputFreq * M / N / (2^OD)
544 In the following steps, we try to work out a best M value given the others are known.
545 To avoid decimal calculation, we use 1000 as multiplier for up to 3 decimal places of accuracy.
546 */
547 M = ulRequestClk * N * odPower * 1000 / pPLL->inputFreq;
548 M = roundedDiv(M, 1000);
549
550 /* M field has only 8 bits, reject value bigger than 8 bits */
551 if (M < 256) {
552 /* Calculate the actual clock for a given M & N */
553 pllClk = pPLL->inputFreq * M / N / odPower / podPower;
554
555 /* How much are we different from the requirement */
556 diff = absDiff(pllClk, ulRequestClk);
557
558 if (diff < bestDiff) {
559 bestDiff = diff;
560
561 /* Store M and N values */
562 pPLL->M = M;
563 pPLL->N = N;
564 pPLL->OD = OD;
565
566 #ifdef VALIDATION_CHIP
567 if (OD > 2)
568 POD = 2;
569 else
570 POD = OD;
571 #endif
572
573 pPLL->POD = POD;
574 }
575 }
576 }
577 }
578 }
579
580 /* Restore input frequency from Khz to hz unit */
581 ulRequestClk *= 1000;
582 pPLL->inputFreq = DEFAULT_INPUT_CLOCK; /* Default reference clock */
583
584 /* Return actual frequency that the PLL can set */
585 ret = calcPLL(pPLL);
586 return ret;
587 }
588
589
590
591
592
593 unsigned int formatPllReg(pll_value_t *pPLL)
594 {
595 unsigned int ulPllReg = 0;
596
597 /* Note that all PLL's have the same format. Here, we just use Panel PLL parameter
598 to work out the bit fields in the register.
599 On returning a 32 bit number, the value can be applied to any PLL in the calling function.
600 */
601 ulPllReg =
602 FIELD_SET( 0, PANEL_PLL_CTRL, BYPASS, OFF)
603 | FIELD_SET( 0, PANEL_PLL_CTRL, POWER, ON)
604 | FIELD_SET( 0, PANEL_PLL_CTRL, INPUT, OSC)
605 #ifndef VALIDATION_CHIP
606 | FIELD_VALUE(0, PANEL_PLL_CTRL, POD, pPLL->POD)
607 #endif
608 | FIELD_VALUE(0, PANEL_PLL_CTRL, OD, pPLL->OD)
609 | FIELD_VALUE(0, PANEL_PLL_CTRL, N, pPLL->N)
610 | FIELD_VALUE(0, PANEL_PLL_CTRL, M, pPLL->M);
611
612 return ulPllReg;
613 }
614
615