1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14:
15:
16: 17: 18: 19: 20:
21: #include "screen.h"
22: #include <sys/segment.h>
23: #include <device/videomode.h>
24: #include <device/em1d512_iic.h>
25:
26: #define ASMUBase 0xc0110000
27: #define PLL2CTRL0 (_UW *)(ASMUBase + 0x008c)
28: #define PLL2CTRL1 (_UW *)(ASMUBase + 0x0090)
29: #define DIVLCDLCLK (_UW *)(ASMUBase + 0x0130)
30: #define PLL_STATUS (_UW *)(ASMUBase + 0x0520)
31:
32: #define LCDBase 0x40270000
33: #define CONTROL (_UW *)(LCDBase + 0x0000)
34: #define QOS (_UW *)(LCDBase + 0x0004)
35: #define DATAREQ (_UW *)(LCDBase + 0x0008)
36: #define LCDOUT (_UW *)(LCDBase + 0x0010)
37: #define BUSSEL (_UW *)(LCDBase + 0x0014)
38: #define STATUS (_UW *)(LCDBase + 0x0018)
39: #define BACKCOLOR (_UW *)(LCDBase + 0x001c)
40: #define AREAADR (_UW *)(LCDBase + 0x0020)
41: #define HOFFSET (_UW *)(LCDBase + 0x0024)
42: #define IFORMAT (_UW *)(LCDBase + 0x0028)
43: #define RESIZE (_UW *)(LCDBase + 0x002c)
44: #define HTOTAL (_UW *)(LCDBase + 0x0030)
45: #define HAREA (_UW *)(LCDBase + 0x0034)
46: #define HEDGE1 (_UW *)(LCDBase + 0x0038)
47: #define HEDGE2 (_UW *)(LCDBase + 0x003c)
48: #define VTOTAL (_UW *)(LCDBase + 0x0040)
49: #define VAREA (_UW *)(LCDBase + 0x0044)
50: #define VEDGE1 (_UW *)(LCDBase + 0x0048)
51: #define VEDGE2 (_UW *)(LCDBase + 0x004c)
52: #define INTSTATUS (_UW *)(LCDBase + 0x0060)
53: #define INTRAWSTATUS (_UW *)(LCDBase + 0x0064)
54: #define INTENSET (_UW *)(LCDBase + 0x0068)
55: #define INTENCLR (_UW *)(LCDBase + 0x006c)
56: #define INTFFCLR (_UW *)(LCDBase + 0x0070)
57: #define FRAMECNT (_UW *)(LCDBase + 0x0074)
58:
59: #define GIOBase(x) (0xc0050000 + 0x00000040 * (x))
60: #define GIO_L 0x00
61: #define GIO_H 0x01
62: #define GIO_HH 0x02
63: #define GIO_HHH 0x08
64: #define GIO_OL(x) (_UW *)(GIOBase(x) + 0x0008)
65: #define GIO_OH(x) (_UW *)(GIOBase(x) + 0x000c)
66:
67:
68: typedef struct {
69: W paneltype;
70: UW pll2ctrl0;
71: UW divlcdlclk;
72:
73: UH hde;
74: UH hrs;
75: UH hre;
76: UH htot;
77: UH vde;
78: UH vrs;
79: UH vre;
80: UH vtot;
81: B hsync;
82: B vsync;
83: } LCDdefs;
84:
85:
86: #define SUPPORT_MODEMAP 00020000000
87: #define DEFAULT_REQMODE DMeWVGAx16
88:
89:
90: LOCAL const LCDdefs LCDparm[] = {
91: {
92:
93: -1, 0x61, 0x51,
94: 800, 840, 968, 1056, 480, 491, 493, 525, -1, -1
95: },
96: };
97:
98:
99: LOCAL W WriteDA9052(W reg, W dat)
100: {
101: #define RETRY 4
102:
103: W er, i;
104: UB cmd[2];
105:
106: for (i = RETRY; i > 0; i--) {
107: cmd[0] = reg << 1;
108: cmd[1] = dat;
109: er = em1d512_spixfer(0, cmd, cmd, sizeof(cmd));
110: if (er >= E_OK) break;
111: }
112:
113: return er;
114: }
115:
116:
117: LOCAL void LCDpower(BOOL power)
118: {
119: LOCAL const UB on_cmd[] = {
120: 54, 0x5a,
121: 70, 0x27,
122: 71, 0x4f,
123: 73, 0xe1,
124: 74, 0xe1,
125: 76, 0xbf,
126: 77, 0xbf,
127: 0, 0x00,
128: };
129: LOCAL const UB off_cmd[] = {
130: 77, 0x00,
131: 76, 0x00,
132: 74, 0x00,
133: 73, 0x00,
134: 71, 0x40,
135: 70, 0x20,
136: 54, 0x1a,
137: 0, 0x00,
138: };
139: const UB *cmd;
140:
141: if (!power) {
142: *GIO_OH(GIO_HH) = 0x00040000;
143: tk_dly_tsk(10);
144: }
145:
146: cmd = power ? on_cmd : off_cmd;
147: while (*cmd) {
148: WriteDA9052(*cmd, *(cmd + 1));
149: cmd += 2;
150: }
151: tk_dly_tsk(10);
152:
153: if (power) {
154: *GIO_OH(GIO_HH) = 0x00040004;
155: tk_dly_tsk(10);
156: }
157:
158: return;
159: }
160:
161:
162: LOCAL void em1_setcmap(COLOR *cmap, W index, W entries)
163: {
164:
165: return;
166: }
167:
168:
169: LOCAL const LCDdefs *find_lcdpar(void)
170: {
171: W i;
172: const LCDdefs *lcd;
173:
174: for (i = 0; i < sizeof(LCDparm) / sizeof(LCDdefs); i++) {
175: lcd = &LCDparm[i];
176:
177:
178: if (lcd->paneltype >= 0 &&
179: lcd->paneltype != Vinf.paneltype) continue;
180:
181:
182: if (lcd->hde != VideoHsize(Vinf.reqmode) ||
183: lcd->vde != VideoVsize(Vinf.reqmode)) continue;
184:
185:
186: return lcd;
187: }
188:
189:
190: return NULL;
191: }
192:
193:
194: LOCAL void pll_setup(UW pll2ctrl0, UW divlcdlclk)
195: {
196: UW imask;
197: W i;
198:
199: DI(imask);
200:
201:
202: *PLL2CTRL1 = 0xff;
203: for (i = 0; i < 1000000 && (*PLL_STATUS & 0x0100); i++) WaitUsec(1);
204:
205:
206: *PLL2CTRL0 = pll2ctrl0;
207: *DIVLCDLCLK = divlcdlclk;
208:
209:
210: *PLL2CTRL1 = 0;
211: for (i = 0; i < 1000000 && !(*PLL_STATUS & 0x0100); i++) WaitUsec(1);
212:
213: EI(imask);
214: return;
215: }
216:
217:
218: LOCAL void em1_setmode(W flg)
219: {
220: const LCDdefs *lcd;
221:
222:
223: lcd = find_lcdpar();
224: if (lcd == NULL) goto fin0;
225:
226:
227: *LCDOUT = 0;
228: LCDpower(FALSE);
229:
230:
231: if (flg < 0) goto fin0;
232:
233:
234: pll_setup(lcd->pll2ctrl0, lcd->divlcdlclk);
235:
236:
237: *BUSSEL = 1;
238: *QOS = 0;
239: *CONTROL= ((lcd->hsync < 0) ? 4 : 0) |
240: ((lcd->vsync < 0) ? 2 : 0);
241: *BACKCOLOR = 0;
242: *AREAADR = (UW)Vinf.framebuf_addr;
243: *HOFFSET = Vinf.framebuf_rowb;
244: *IFORMAT = 1;
245: *HAREA = lcd->hde;
246: *HEDGE1 = lcd->hrs - lcd->hde;
247: *HEDGE2 = lcd->hre - lcd->hde;
248: *HTOTAL = lcd->htot;
249: *VAREA = lcd->vde;
250: *VEDGE1 = lcd->vrs - lcd->vde;
251: *VEDGE2 = lcd->vre - lcd->vde;
252: *VTOTAL = lcd->vtot;
253: *INTENCLR = ~0;
254:
255:
256: if (flg) MEMSET(Vinf.f_addr, 0, Vinf.framebuf_total);
257:
258:
259: LCDpower(TRUE);
260: *LCDOUT = 1;
261:
262: fin0:
263: return;
264: }
265:
266:
267: LOCAL void em1_suspend(BOOL suspend)
268: {
269:
270: if (suspend) MEMSET(Vinf.f_addr, 0, Vinf.framebuf_total);
271:
272:
273: if (suspend) {
274: *LCDOUT = 0;
275: LCDpower(FALSE);
276: } else {
277: LCDpower(TRUE);
278: *LCDOUT = 1;
279: }
280:
281: return;
282: }
283:
284: 285: 286: 287: 288: 289: 290: 291: 292: 293: 294: 295: 296: 297: 298: 299: 300: 301: 302: 303: 304: 305: 306: 307: 308: 309: 310: 311: 312: 313: 314: 315: 316: 317: 318: 319: 320: 321: 322: 323: 324: 325: 326: 327: 328: 329: 330: 331: 332: 333: 334: 335: 336: 337: 338: 339: 340: 341: 342: 343: 344: 345: 346: 347: 348: 349: 350:
351: EXPORT W EM1LCDCInit(void)
352: {
353: W fbsz, rowb, result;
354:
355:
356: if ( (result = em1d512_iicspi_svc(TRUE)) < E_OK ) goto fin0;
357:
358:
359: if (!(SUPPORT_MODEMAP & (1 << Vinf.reqmode))) {
360: Vinf.reqmode = DEFAULT_REQMODE;
361: }
362:
363:
364: rowb = VideoHsize(Vinf.reqmode) * 2;
365: fbsz = rowb * VideoVsize(Vinf.reqmode);
366:
367: Vinf.fb_width = VideoHsize(Vinf.reqmode);
368: Vinf.fb_height = VideoVsize(Vinf.reqmode);
369:
370:
371:
372: Vinf.f_addr = getPhyMemory(fbsz + 16, &Vinf.framebuf_addr);
373: if (Vinf.f_addr == NULL) { result = E_NOMEM; goto fin0; }
374:
375:
376: STRNCPY(Vinf.chipinf, "EMMA-1 Mobile LCD Controller", L_CHIPINF);
377: Vinf.framebuf_total = fbsz;
378: Vinf.framebuf_rowb = rowb;
379: Vinf.curmode = Vinf.reqmode;
380: Vinf.attr |= (LINEAR_FRAMEBUF | DACBITS_8 |
381: NEED_FINPROC | NEED_SUSRESPROC);
382: Vinf.attr &= ~BPP_24;
383: Vinf.fn_setcmap = em1_setcmap;
384: Vinf.fn_setmode = em1_setmode;
385: Vinf.fn_susres = em1_suspend;
386: Vinf.modemap = SUPPORT_MODEMAP;
387:
388: DP(("EM1LCDCInit(): Vinf.framebuf_addr %#x - %#x (%#x - %#x)\n",
389: Vinf.framebuf_addr, Vinf.framebuf_addr + Vinf.framebuf_total - 1,
390: Vinf.f_addr, Vinf.f_addr + Vinf.framebuf_total - 1));
391:
392: result = 1;
393: fin0:
394: return result;
395: }