diff options
author | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
commit | 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch) | |
tree | 0bba044c4ce775e45a88a51686b5d9f90697ea9d /drivers/video/w100fb.c |
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history,
even though we have it. We can create a separate "historical" git
archive of that later if we want to, and in the meantime it's about
3.2GB when imported into git - space that would just make the early
git days unnecessarily complicated, when we don't have a lot of good
infrastructure for it.
Let it rip!
Diffstat (limited to 'drivers/video/w100fb.c')
-rw-r--r-- | drivers/video/w100fb.c | 1873 |
1 files changed, 1873 insertions, 0 deletions
diff --git a/drivers/video/w100fb.c b/drivers/video/w100fb.c new file mode 100644 index 000000000000..057e154c8858 --- /dev/null +++ b/drivers/video/w100fb.c | |||
@@ -0,0 +1,1873 @@ | |||
1 | /* | ||
2 | * linux/drivers/video/w100fb.c | ||
3 | * | ||
4 | * Frame Buffer Device for ATI Imageon w100 (Wallaby) | ||
5 | * | ||
6 | * Copyright (C) 2002, ATI Corp. | ||
7 | * Copyright (C) 2004-2005 Richard Purdie | ||
8 | * | ||
9 | * Rewritten for 2.6 by Richard Purdie <rpurdie@rpsys.net> | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or modify | ||
12 | * it under the terms of the GNU General Public License version 2 as | ||
13 | * published by the Free Software Foundation. | ||
14 | * | ||
15 | */ | ||
16 | |||
17 | #include <linux/delay.h> | ||
18 | #include <linux/fb.h> | ||
19 | #include <linux/init.h> | ||
20 | #include <linux/kernel.h> | ||
21 | #include <linux/mm.h> | ||
22 | #include <linux/device.h> | ||
23 | #include <linux/string.h> | ||
24 | #include <linux/proc_fs.h> | ||
25 | #include <asm/io.h> | ||
26 | #include <asm/uaccess.h> | ||
27 | #include <video/w100fb.h> | ||
28 | #include "w100fb.h" | ||
29 | |||
30 | /* | ||
31 | * Prototypes | ||
32 | */ | ||
33 | static void w100fb_save_buffer(void); | ||
34 | static void w100fb_clear_buffer(void); | ||
35 | static void w100fb_restore_buffer(void); | ||
36 | static void w100fb_clear_screen(u32 mode, long int offset); | ||
37 | static void w100_resume(void); | ||
38 | static void w100_suspend(u32 mode); | ||
39 | static void w100_init_qvga_rotation(u16 deg); | ||
40 | static void w100_init_vga_rotation(u16 deg); | ||
41 | static void w100_vsync(void); | ||
42 | static void w100_init_sharp_lcd(u32 mode); | ||
43 | static void w100_pwm_setup(void); | ||
44 | static void w100_InitExtMem(u32 mode); | ||
45 | static void w100_hw_init(void); | ||
46 | static u16 w100_set_fastsysclk(u16 Freq); | ||
47 | |||
48 | static void lcdtg_hw_init(u32 mode); | ||
49 | static void lcdtg_lcd_change(u32 mode); | ||
50 | static void lcdtg_resume(void); | ||
51 | static void lcdtg_suspend(void); | ||
52 | |||
53 | |||
54 | /* Register offsets & lengths */ | ||
55 | #define REMAPPED_FB_LEN 0x15ffff | ||
56 | |||
57 | #define BITS_PER_PIXEL 16 | ||
58 | |||
59 | /* Pseudo palette size */ | ||
60 | #define MAX_PALETTES 16 | ||
61 | |||
62 | /* for resolution change */ | ||
63 | #define LCD_MODE_INIT (-1) | ||
64 | #define LCD_MODE_480 0 | ||
65 | #define LCD_MODE_320 1 | ||
66 | #define LCD_MODE_240 2 | ||
67 | #define LCD_MODE_640 3 | ||
68 | |||
69 | #define LCD_SHARP_QVGA 0 | ||
70 | #define LCD_SHARP_VGA 1 | ||
71 | |||
72 | #define LCD_MODE_PORTRAIT 0 | ||
73 | #define LCD_MODE_LANDSCAPE 1 | ||
74 | |||
75 | #define W100_SUSPEND_EXTMEM 0 | ||
76 | #define W100_SUSPEND_ALL 1 | ||
77 | |||
78 | /* General frame buffer data structures */ | ||
79 | struct w100fb_par { | ||
80 | u32 xres; | ||
81 | u32 yres; | ||
82 | int fastsysclk_mode; | ||
83 | int lcdMode; | ||
84 | int rotation_flag; | ||
85 | int blanking_flag; | ||
86 | int comadj; | ||
87 | int phadadj; | ||
88 | }; | ||
89 | |||
90 | static struct w100fb_par *current_par; | ||
91 | |||
92 | /* Remapped addresses for base cfg, memmapped regs and the frame buffer itself */ | ||
93 | static void *remapped_base; | ||
94 | static void *remapped_regs; | ||
95 | static void *remapped_fbuf; | ||
96 | |||
97 | /* External Function */ | ||
98 | static void(*w100fb_ssp_send)(u8 adrs, u8 data); | ||
99 | |||
100 | /* | ||
101 | * Sysfs functions | ||
102 | */ | ||
103 | |||
104 | static ssize_t rotation_show(struct device *dev, char *buf) | ||
105 | { | ||
106 | struct fb_info *info = dev_get_drvdata(dev); | ||
107 | struct w100fb_par *par=info->par; | ||
108 | |||
109 | return sprintf(buf, "%d\n",par->rotation_flag); | ||
110 | } | ||
111 | |||
112 | static ssize_t rotation_store(struct device *dev, const char *buf, size_t count) | ||
113 | { | ||
114 | unsigned int rotate; | ||
115 | struct fb_info *info = dev_get_drvdata(dev); | ||
116 | struct w100fb_par *par=info->par; | ||
117 | |||
118 | rotate = simple_strtoul(buf, NULL, 10); | ||
119 | |||
120 | if (rotate > 0) par->rotation_flag = 1; | ||
121 | else par->rotation_flag = 0; | ||
122 | |||
123 | if (par->lcdMode == LCD_MODE_320) | ||
124 | w100_init_qvga_rotation(par->rotation_flag ? 270 : 90); | ||
125 | else if (par->lcdMode == LCD_MODE_240) | ||
126 | w100_init_qvga_rotation(par->rotation_flag ? 180 : 0); | ||
127 | else if (par->lcdMode == LCD_MODE_640) | ||
128 | w100_init_vga_rotation(par->rotation_flag ? 270 : 90); | ||
129 | else if (par->lcdMode == LCD_MODE_480) | ||
130 | w100_init_vga_rotation(par->rotation_flag ? 180 : 0); | ||
131 | |||
132 | return count; | ||
133 | } | ||
134 | |||
135 | static DEVICE_ATTR(rotation, 0644, rotation_show, rotation_store); | ||
136 | |||
137 | static ssize_t w100fb_reg_read(struct device *dev, const char *buf, size_t count) | ||
138 | { | ||
139 | unsigned long param; | ||
140 | unsigned long regs; | ||
141 | regs = simple_strtoul(buf, NULL, 16); | ||
142 | param = readl(remapped_regs + regs); | ||
143 | printk("Read Register 0x%08lX: 0x%08lX\n", regs, param); | ||
144 | return count; | ||
145 | } | ||
146 | |||
147 | static DEVICE_ATTR(reg_read, 0200, NULL, w100fb_reg_read); | ||
148 | |||
149 | static ssize_t w100fb_reg_write(struct device *dev, const char *buf, size_t count) | ||
150 | { | ||
151 | unsigned long regs; | ||
152 | unsigned long param; | ||
153 | sscanf(buf, "%lx %lx", ®s, ¶m); | ||
154 | |||
155 | if (regs <= 0x2000) { | ||
156 | printk("Write Register 0x%08lX: 0x%08lX\n", regs, param); | ||
157 | writel(param, remapped_regs + regs); | ||
158 | } | ||
159 | |||
160 | return count; | ||
161 | } | ||
162 | |||
163 | static DEVICE_ATTR(reg_write, 0200, NULL, w100fb_reg_write); | ||
164 | |||
165 | |||
166 | static ssize_t fastsysclk_show(struct device *dev, char *buf) | ||
167 | { | ||
168 | struct fb_info *info = dev_get_drvdata(dev); | ||
169 | struct w100fb_par *par=info->par; | ||
170 | |||
171 | return sprintf(buf, "%d\n",par->fastsysclk_mode); | ||
172 | } | ||
173 | |||
174 | static ssize_t fastsysclk_store(struct device *dev, const char *buf, size_t count) | ||
175 | { | ||
176 | int param; | ||
177 | struct fb_info *info = dev_get_drvdata(dev); | ||
178 | struct w100fb_par *par=info->par; | ||
179 | |||
180 | param = simple_strtoul(buf, NULL, 10); | ||
181 | |||
182 | if (param == 75) { | ||
183 | printk("Set fastsysclk %d\n", param); | ||
184 | par->fastsysclk_mode = param; | ||
185 | w100_set_fastsysclk(par->fastsysclk_mode); | ||
186 | } else if (param == 100) { | ||
187 | printk("Set fastsysclk %d\n", param); | ||
188 | par->fastsysclk_mode = param; | ||
189 | w100_set_fastsysclk(par->fastsysclk_mode); | ||
190 | } | ||
191 | return count; | ||
192 | } | ||
193 | |||
194 | static DEVICE_ATTR(fastsysclk, 0644, fastsysclk_show, fastsysclk_store); | ||
195 | |||
196 | /* | ||
197 | * The touchscreen on this device needs certain information | ||
198 | * from the video driver to function correctly. We export it here. | ||
199 | */ | ||
200 | int w100fb_get_xres(void) { | ||
201 | return current_par->xres; | ||
202 | } | ||
203 | |||
204 | int w100fb_get_blanking(void) { | ||
205 | return current_par->blanking_flag; | ||
206 | } | ||
207 | |||
208 | int w100fb_get_fastsysclk(void) { | ||
209 | return current_par->fastsysclk_mode; | ||
210 | } | ||
211 | EXPORT_SYMBOL(w100fb_get_xres); | ||
212 | EXPORT_SYMBOL(w100fb_get_blanking); | ||
213 | EXPORT_SYMBOL(w100fb_get_fastsysclk); | ||
214 | |||
215 | |||
216 | /* | ||
217 | * Set a palette value from rgb components | ||
218 | */ | ||
219 | static int w100fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, | ||
220 | u_int trans, struct fb_info *info) | ||
221 | { | ||
222 | unsigned int val; | ||
223 | int ret = 1; | ||
224 | |||
225 | /* | ||
226 | * If greyscale is true, then we convert the RGB value | ||
227 | * to greyscale no matter what visual we are using. | ||
228 | */ | ||
229 | if (info->var.grayscale) | ||
230 | red = green = blue = (19595 * red + 38470 * green + 7471 * blue) >> 16; | ||
231 | |||
232 | /* | ||
233 | * 16-bit True Colour. We encode the RGB value | ||
234 | * according to the RGB bitfield information. | ||
235 | */ | ||
236 | if (regno < MAX_PALETTES) { | ||
237 | |||
238 | u32 *pal = info->pseudo_palette; | ||
239 | |||
240 | val = (red & 0xf800) | ((green & 0xfc00) >> 5) | ((blue & 0xf800) >> 11); | ||
241 | pal[regno] = val; | ||
242 | ret = 0; | ||
243 | } | ||
244 | return ret; | ||
245 | } | ||
246 | |||
247 | |||
248 | /* | ||
249 | * Blank the display based on value in blank_mode | ||
250 | */ | ||
251 | static int w100fb_blank(int blank_mode, struct fb_info *info) | ||
252 | { | ||
253 | struct w100fb_par *par; | ||
254 | par=info->par; | ||
255 | |||
256 | switch(blank_mode) { | ||
257 | |||
258 | case FB_BLANK_NORMAL: /* Normal blanking */ | ||
259 | case FB_BLANK_VSYNC_SUSPEND: /* VESA blank (vsync off) */ | ||
260 | case FB_BLANK_HSYNC_SUSPEND: /* VESA blank (hsync off) */ | ||
261 | case FB_BLANK_POWERDOWN: /* Poweroff */ | ||
262 | if (par->blanking_flag == 0) { | ||
263 | w100fb_save_buffer(); | ||
264 | lcdtg_suspend(); | ||
265 | par->blanking_flag = 1; | ||
266 | } | ||
267 | break; | ||
268 | |||
269 | case FB_BLANK_UNBLANK: /* Unblanking */ | ||
270 | if (par->blanking_flag != 0) { | ||
271 | w100fb_restore_buffer(); | ||
272 | lcdtg_resume(); | ||
273 | par->blanking_flag = 0; | ||
274 | } | ||
275 | break; | ||
276 | } | ||
277 | return 0; | ||
278 | } | ||
279 | |||
280 | /* | ||
281 | * Change the resolution by calling the appropriate hardware functions | ||
282 | */ | ||
283 | static void w100fb_changeres(int rotate_mode, u32 mode) | ||
284 | { | ||
285 | u16 rotation=0; | ||
286 | |||
287 | switch(rotate_mode) { | ||
288 | case LCD_MODE_LANDSCAPE: | ||
289 | rotation=(current_par->rotation_flag ? 270 : 90); | ||
290 | break; | ||
291 | case LCD_MODE_PORTRAIT: | ||
292 | rotation=(current_par->rotation_flag ? 180 : 0); | ||
293 | break; | ||
294 | } | ||
295 | |||
296 | w100_pwm_setup(); | ||
297 | switch(mode) { | ||
298 | case LCD_SHARP_QVGA: | ||
299 | w100_vsync(); | ||
300 | w100_suspend(W100_SUSPEND_EXTMEM); | ||
301 | w100_init_sharp_lcd(LCD_SHARP_QVGA); | ||
302 | w100_init_qvga_rotation(rotation); | ||
303 | w100_InitExtMem(LCD_SHARP_QVGA); | ||
304 | w100fb_clear_screen(LCD_SHARP_QVGA, 0); | ||
305 | lcdtg_lcd_change(LCD_SHARP_QVGA); | ||
306 | break; | ||
307 | case LCD_SHARP_VGA: | ||
308 | w100fb_clear_screen(LCD_SHARP_QVGA, 0); | ||
309 | writel(0xBFFFA000, remapped_regs + mmMC_EXT_MEM_LOCATION); | ||
310 | w100_InitExtMem(LCD_SHARP_VGA); | ||
311 | w100fb_clear_screen(LCD_SHARP_VGA, 0x200000); | ||
312 | w100_vsync(); | ||
313 | w100_init_sharp_lcd(LCD_SHARP_VGA); | ||
314 | if (rotation != 0) | ||
315 | w100_init_vga_rotation(rotation); | ||
316 | lcdtg_lcd_change(LCD_SHARP_VGA); | ||
317 | break; | ||
318 | } | ||
319 | } | ||
320 | |||
321 | /* | ||
322 | * Set up the display for the fb subsystem | ||
323 | */ | ||
324 | static void w100fb_activate_var(struct fb_info *info) | ||
325 | { | ||
326 | u32 temp32; | ||
327 | struct w100fb_par *par=info->par; | ||
328 | struct fb_var_screeninfo *var = &info->var; | ||
329 | |||
330 | /* Set the hardware to 565 */ | ||
331 | temp32 = readl(remapped_regs + mmDISP_DEBUG2); | ||
332 | temp32 &= 0xff7fffff; | ||
333 | temp32 |= 0x00800000; | ||
334 | writel(temp32, remapped_regs + mmDISP_DEBUG2); | ||
335 | |||
336 | if (par->lcdMode == LCD_MODE_INIT) { | ||
337 | w100_init_sharp_lcd(LCD_SHARP_VGA); | ||
338 | w100_init_vga_rotation(par->rotation_flag ? 270 : 90); | ||
339 | par->lcdMode = LCD_MODE_640; | ||
340 | lcdtg_hw_init(LCD_SHARP_VGA); | ||
341 | } else if (var->xres == 320 && var->yres == 240) { | ||
342 | if (par->lcdMode != LCD_MODE_320) { | ||
343 | w100fb_changeres(LCD_MODE_LANDSCAPE, LCD_SHARP_QVGA); | ||
344 | par->lcdMode = LCD_MODE_320; | ||
345 | } | ||
346 | } else if (var->xres == 240 && var->yres == 320) { | ||
347 | if (par->lcdMode != LCD_MODE_240) { | ||
348 | w100fb_changeres(LCD_MODE_PORTRAIT, LCD_SHARP_QVGA); | ||
349 | par->lcdMode = LCD_MODE_240; | ||
350 | } | ||
351 | } else if (var->xres == 640 && var->yres == 480) { | ||
352 | if (par->lcdMode != LCD_MODE_640) { | ||
353 | w100fb_changeres(LCD_MODE_LANDSCAPE, LCD_SHARP_VGA); | ||
354 | par->lcdMode = LCD_MODE_640; | ||
355 | } | ||
356 | } else if (var->xres == 480 && var->yres == 640) { | ||
357 | if (par->lcdMode != LCD_MODE_480) { | ||
358 | w100fb_changeres(LCD_MODE_PORTRAIT, LCD_SHARP_VGA); | ||
359 | par->lcdMode = LCD_MODE_480; | ||
360 | } | ||
361 | } else printk(KERN_ERR "W100FB: Resolution error!\n"); | ||
362 | } | ||
363 | |||
364 | |||
365 | /* | ||
366 | * w100fb_check_var(): | ||
367 | * Get the video params out of 'var'. If a value doesn't fit, round it up, | ||
368 | * if it's too big, return -EINVAL. | ||
369 | * | ||
370 | */ | ||
371 | static int w100fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) | ||
372 | { | ||
373 | if (var->xres < var->yres) { /* Portrait mode */ | ||
374 | if ((var->xres > 480) || (var->yres > 640)) { | ||
375 | return -EINVAL; | ||
376 | } else if ((var->xres > 240) || (var->yres > 320)) { | ||
377 | var->xres = 480; | ||
378 | var->yres = 640; | ||
379 | } else { | ||
380 | var->xres = 240; | ||
381 | var->yres = 320; | ||
382 | } | ||
383 | } else { /* Landscape mode */ | ||
384 | if ((var->xres > 640) || (var->yres > 480)) { | ||
385 | return -EINVAL; | ||
386 | } else if ((var->xres > 320) || (var->yres > 240)) { | ||
387 | var->xres = 640; | ||
388 | var->yres = 480; | ||
389 | } else { | ||
390 | var->xres = 320; | ||
391 | var->yres = 240; | ||
392 | } | ||
393 | } | ||
394 | |||
395 | var->xres_virtual = max(var->xres_virtual, var->xres); | ||
396 | var->yres_virtual = max(var->yres_virtual, var->yres); | ||
397 | |||
398 | if (var->bits_per_pixel > BITS_PER_PIXEL) | ||
399 | return -EINVAL; | ||
400 | else | ||
401 | var->bits_per_pixel = BITS_PER_PIXEL; | ||
402 | |||
403 | var->red.offset = 11; | ||
404 | var->red.length = 5; | ||
405 | var->green.offset = 5; | ||
406 | var->green.length = 6; | ||
407 | var->blue.offset = 0; | ||
408 | var->blue.length = 5; | ||
409 | var->transp.offset = var->transp.length = 0; | ||
410 | |||
411 | var->nonstd = 0; | ||
412 | |||
413 | var->height = -1; | ||
414 | var->width = -1; | ||
415 | var->vmode = FB_VMODE_NONINTERLACED; | ||
416 | |||
417 | var->sync = 0; | ||
418 | var->pixclock = 0x04; /* 171521; */ | ||
419 | |||
420 | return 0; | ||
421 | } | ||
422 | |||
423 | |||
424 | /* | ||
425 | * w100fb_set_par(): | ||
426 | * Set the user defined part of the display for the specified console | ||
427 | * by looking at the values in info.var | ||
428 | */ | ||
429 | static int w100fb_set_par(struct fb_info *info) | ||
430 | { | ||
431 | struct w100fb_par *par=info->par; | ||
432 | |||
433 | par->xres = info->var.xres; | ||
434 | par->yres = info->var.yres; | ||
435 | |||
436 | info->fix.visual = FB_VISUAL_TRUECOLOR; | ||
437 | |||
438 | info->fix.ypanstep = 0; | ||
439 | info->fix.ywrapstep = 0; | ||
440 | |||
441 | if (par->blanking_flag) | ||
442 | w100fb_clear_buffer(); | ||
443 | |||
444 | w100fb_activate_var(info); | ||
445 | |||
446 | if (par->lcdMode == LCD_MODE_480) { | ||
447 | info->fix.line_length = (480 * BITS_PER_PIXEL) / 8; | ||
448 | info->fix.smem_len = 0x200000; | ||
449 | } else if (par->lcdMode == LCD_MODE_320) { | ||
450 | info->fix.line_length = (320 * BITS_PER_PIXEL) / 8; | ||
451 | info->fix.smem_len = 0x60000; | ||
452 | } else if (par->lcdMode == LCD_MODE_240) { | ||
453 | info->fix.line_length = (240 * BITS_PER_PIXEL) / 8; | ||
454 | info->fix.smem_len = 0x60000; | ||
455 | } else if (par->lcdMode == LCD_MODE_INIT || par->lcdMode == LCD_MODE_640) { | ||
456 | info->fix.line_length = (640 * BITS_PER_PIXEL) / 8; | ||
457 | info->fix.smem_len = 0x200000; | ||
458 | } | ||
459 | |||
460 | return 0; | ||
461 | } | ||
462 | |||
463 | |||
464 | /* | ||
465 | * Frame buffer operations | ||
466 | */ | ||
467 | static struct fb_ops w100fb_ops = { | ||
468 | .owner = THIS_MODULE, | ||
469 | .fb_check_var = w100fb_check_var, | ||
470 | .fb_set_par = w100fb_set_par, | ||
471 | .fb_setcolreg = w100fb_setcolreg, | ||
472 | .fb_blank = w100fb_blank, | ||
473 | .fb_fillrect = cfb_fillrect, | ||
474 | .fb_copyarea = cfb_copyarea, | ||
475 | .fb_imageblit = cfb_imageblit, | ||
476 | .fb_cursor = soft_cursor, | ||
477 | }; | ||
478 | |||
479 | |||
480 | static void w100fb_clear_screen(u32 mode, long int offset) | ||
481 | { | ||
482 | int i, numPix = 0; | ||
483 | |||
484 | if (mode == LCD_SHARP_VGA) | ||
485 | numPix = 640 * 480; | ||
486 | else if (mode == LCD_SHARP_QVGA) | ||
487 | numPix = 320 * 240; | ||
488 | |||
489 | for (i = 0; i < numPix; i++) | ||
490 | writew(0xffff, remapped_fbuf + offset + (2*i)); | ||
491 | } | ||
492 | |||
493 | |||
494 | /* Need to split up the buffers to stay within the limits of kmalloc */ | ||
495 | #define W100_BUF_NUM 6 | ||
496 | static uint32_t *gSaveImagePtr[W100_BUF_NUM] = { NULL }; | ||
497 | |||
498 | static void w100fb_save_buffer(void) | ||
499 | { | ||
500 | int i, j, bufsize; | ||
501 | |||
502 | bufsize=(current_par->xres * current_par->yres * BITS_PER_PIXEL / 8) / W100_BUF_NUM; | ||
503 | for (i = 0; i < W100_BUF_NUM; i++) { | ||
504 | if (gSaveImagePtr[i] == NULL) | ||
505 | gSaveImagePtr[i] = kmalloc(bufsize, GFP_KERNEL); | ||
506 | if (gSaveImagePtr[i] == NULL) { | ||
507 | w100fb_clear_buffer(); | ||
508 | printk(KERN_WARNING "can't alloc pre-off image buffer %d\n", i); | ||
509 | break; | ||
510 | } | ||
511 | for (j = 0; j < bufsize/4; j++) | ||
512 | *(gSaveImagePtr[i] + j) = readl(remapped_fbuf + (bufsize*i) + j*4); | ||
513 | } | ||
514 | } | ||
515 | |||
516 | |||
517 | static void w100fb_restore_buffer(void) | ||
518 | { | ||
519 | int i, j, bufsize; | ||
520 | |||
521 | bufsize=(current_par->xres * current_par->yres * BITS_PER_PIXEL / 8) / W100_BUF_NUM; | ||
522 | for (i = 0; i < W100_BUF_NUM; i++) { | ||
523 | if (gSaveImagePtr[i] == NULL) { | ||
524 | printk(KERN_WARNING "can't find pre-off image buffer %d\n", i); | ||
525 | w100fb_clear_buffer(); | ||
526 | break; | ||
527 | } | ||
528 | for (j = 0; j < (bufsize/4); j++) | ||
529 | writel(*(gSaveImagePtr[i] + j),remapped_fbuf + (bufsize*i) + (j*4)); | ||
530 | kfree(gSaveImagePtr[i]); | ||
531 | gSaveImagePtr[i] = NULL; | ||
532 | } | ||
533 | } | ||
534 | |||
535 | |||
536 | static void w100fb_clear_buffer(void) | ||
537 | { | ||
538 | int i; | ||
539 | for (i = 0; i < W100_BUF_NUM; i++) { | ||
540 | kfree(gSaveImagePtr[i]); | ||
541 | gSaveImagePtr[i] = NULL; | ||
542 | } | ||
543 | } | ||
544 | |||
545 | |||
546 | #ifdef CONFIG_PM | ||
547 | static int w100fb_suspend(struct device *dev, u32 state, u32 level) | ||
548 | { | ||
549 | if (level == SUSPEND_POWER_DOWN) { | ||
550 | struct fb_info *info = dev_get_drvdata(dev); | ||
551 | struct w100fb_par *par=info->par; | ||
552 | |||
553 | w100fb_save_buffer(); | ||
554 | lcdtg_suspend(); | ||
555 | w100_suspend(W100_SUSPEND_ALL); | ||
556 | par->blanking_flag = 1; | ||
557 | } | ||
558 | return 0; | ||
559 | } | ||
560 | |||
561 | static int w100fb_resume(struct device *dev, u32 level) | ||
562 | { | ||
563 | if (level == RESUME_POWER_ON) { | ||
564 | struct fb_info *info = dev_get_drvdata(dev); | ||
565 | struct w100fb_par *par=info->par; | ||
566 | |||
567 | w100_resume(); | ||
568 | w100fb_restore_buffer(); | ||
569 | lcdtg_resume(); | ||
570 | par->blanking_flag = 0; | ||
571 | } | ||
572 | return 0; | ||
573 | } | ||
574 | #else | ||
575 | #define w100fb_suspend NULL | ||
576 | #define w100fb_resume NULL | ||
577 | #endif | ||
578 | |||
579 | |||
580 | int __init w100fb_probe(struct device *dev) | ||
581 | { | ||
582 | struct w100fb_mach_info *inf; | ||
583 | struct fb_info *info; | ||
584 | struct w100fb_par *par; | ||
585 | struct platform_device *pdev = to_platform_device(dev); | ||
586 | struct resource *mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
587 | |||
588 | if (!mem) | ||
589 | return -EINVAL; | ||
590 | |||
591 | /* remap the areas we're going to use */ | ||
592 | remapped_base = ioremap_nocache(mem->start+W100_CFG_BASE, W100_CFG_LEN); | ||
593 | if (remapped_base == NULL) | ||
594 | return -EIO; | ||
595 | |||
596 | remapped_regs = ioremap_nocache(mem->start+W100_REG_BASE, W100_REG_LEN); | ||
597 | if (remapped_regs == NULL) { | ||
598 | iounmap(remapped_base); | ||
599 | return -EIO; | ||
600 | } | ||
601 | |||
602 | remapped_fbuf = ioremap_nocache(mem->start+MEM_EXT_BASE_VALUE, REMAPPED_FB_LEN); | ||
603 | if (remapped_fbuf == NULL) { | ||
604 | iounmap(remapped_base); | ||
605 | iounmap(remapped_regs); | ||
606 | return -EIO; | ||
607 | } | ||
608 | |||
609 | info=framebuffer_alloc(sizeof(struct w100fb_par), dev); | ||
610 | if (!info) { | ||
611 | iounmap(remapped_base); | ||
612 | iounmap(remapped_regs); | ||
613 | iounmap(remapped_fbuf); | ||
614 | return -ENOMEM; | ||
615 | } | ||
616 | |||
617 | info->device=dev; | ||
618 | par = info->par; | ||
619 | current_par=info->par; | ||
620 | dev_set_drvdata(dev, info); | ||
621 | |||
622 | inf = dev->platform_data; | ||
623 | par->phadadj = inf->phadadj; | ||
624 | par->comadj = inf->comadj; | ||
625 | par->fastsysclk_mode = 75; | ||
626 | par->lcdMode = LCD_MODE_INIT; | ||
627 | par->rotation_flag=0; | ||
628 | par->blanking_flag=0; | ||
629 | w100fb_ssp_send = inf->w100fb_ssp_send; | ||
630 | |||
631 | w100_hw_init(); | ||
632 | w100_pwm_setup(); | ||
633 | |||
634 | info->pseudo_palette = kmalloc(sizeof (u32) * MAX_PALETTES, GFP_KERNEL); | ||
635 | if (!info->pseudo_palette) { | ||
636 | iounmap(remapped_base); | ||
637 | iounmap(remapped_regs); | ||
638 | iounmap(remapped_fbuf); | ||
639 | return -ENOMEM; | ||
640 | } | ||
641 | |||
642 | info->fbops = &w100fb_ops; | ||
643 | info->flags = FBINFO_DEFAULT; | ||
644 | info->node = -1; | ||
645 | info->screen_base = remapped_fbuf; | ||
646 | info->screen_size = REMAPPED_FB_LEN; | ||
647 | |||
648 | info->var.xres = 640; | ||
649 | info->var.xres_virtual = info->var.xres; | ||
650 | info->var.yres = 480; | ||
651 | info->var.yres_virtual = info->var.yres; | ||
652 | info->var.pixclock = 0x04; /* 171521; */ | ||
653 | info->var.sync = 0; | ||
654 | info->var.grayscale = 0; | ||
655 | info->var.xoffset = info->var.yoffset = 0; | ||
656 | info->var.accel_flags = 0; | ||
657 | info->var.activate = FB_ACTIVATE_NOW; | ||
658 | |||
659 | strcpy(info->fix.id, "w100fb"); | ||
660 | info->fix.type = FB_TYPE_PACKED_PIXELS; | ||
661 | info->fix.type_aux = 0; | ||
662 | info->fix.accel = FB_ACCEL_NONE; | ||
663 | info->fix.smem_start = mem->start+MEM_EXT_BASE_VALUE; | ||
664 | info->fix.mmio_start = mem->start+W100_REG_BASE; | ||
665 | info->fix.mmio_len = W100_REG_LEN; | ||
666 | |||
667 | w100fb_check_var(&info->var, info); | ||
668 | w100fb_set_par(info); | ||
669 | |||
670 | if (register_framebuffer(info) < 0) { | ||
671 | kfree(info->pseudo_palette); | ||
672 | iounmap(remapped_base); | ||
673 | iounmap(remapped_regs); | ||
674 | iounmap(remapped_fbuf); | ||
675 | return -EINVAL; | ||
676 | } | ||
677 | |||
678 | device_create_file(dev, &dev_attr_fastsysclk); | ||
679 | device_create_file(dev, &dev_attr_reg_read); | ||
680 | device_create_file(dev, &dev_attr_reg_write); | ||
681 | device_create_file(dev, &dev_attr_rotation); | ||
682 | |||
683 | printk(KERN_INFO "fb%d: %s frame buffer device\n", info->node, info->fix.id); | ||
684 | return 0; | ||
685 | } | ||
686 | |||
687 | |||
688 | static int w100fb_remove(struct device *dev) | ||
689 | { | ||
690 | struct fb_info *info = dev_get_drvdata(dev); | ||
691 | |||
692 | device_remove_file(dev, &dev_attr_fastsysclk); | ||
693 | device_remove_file(dev, &dev_attr_reg_read); | ||
694 | device_remove_file(dev, &dev_attr_reg_write); | ||
695 | device_remove_file(dev, &dev_attr_rotation); | ||
696 | |||
697 | unregister_framebuffer(info); | ||
698 | |||
699 | w100fb_clear_buffer(); | ||
700 | kfree(info->pseudo_palette); | ||
701 | |||
702 | iounmap(remapped_base); | ||
703 | iounmap(remapped_regs); | ||
704 | iounmap(remapped_fbuf); | ||
705 | |||
706 | framebuffer_release(info); | ||
707 | |||
708 | return 0; | ||
709 | } | ||
710 | |||
711 | |||
712 | /* ------------------- chipset specific functions -------------------------- */ | ||
713 | |||
714 | |||
715 | static void w100_soft_reset(void) | ||
716 | { | ||
717 | u16 val = readw((u16 *) remapped_base + cfgSTATUS); | ||
718 | writew(val | 0x08, (u16 *) remapped_base + cfgSTATUS); | ||
719 | udelay(100); | ||
720 | writew(0x00, (u16 *) remapped_base + cfgSTATUS); | ||
721 | udelay(100); | ||
722 | } | ||
723 | |||
724 | /* | ||
725 | * Initialization of critical w100 hardware | ||
726 | */ | ||
727 | static void w100_hw_init(void) | ||
728 | { | ||
729 | u32 temp32; | ||
730 | union cif_cntl_u cif_cntl; | ||
731 | union intf_cntl_u intf_cntl; | ||
732 | union cfgreg_base_u cfgreg_base; | ||
733 | union wrap_top_dir_u wrap_top_dir; | ||
734 | union cif_read_dbg_u cif_read_dbg; | ||
735 | union cpu_defaults_u cpu_default; | ||
736 | union cif_write_dbg_u cif_write_dbg; | ||
737 | union wrap_start_dir_u wrap_start_dir; | ||
738 | union mc_ext_mem_location_u mc_ext_mem_loc; | ||
739 | union cif_io_u cif_io; | ||
740 | |||
741 | w100_soft_reset(); | ||
742 | |||
743 | /* This is what the fpga_init code does on reset. May be wrong | ||
744 | but there is little info available */ | ||
745 | writel(0x31, remapped_regs + mmSCRATCH_UMSK); | ||
746 | for (temp32 = 0; temp32 < 10000; temp32++) | ||
747 | readl(remapped_regs + mmSCRATCH_UMSK); | ||
748 | writel(0x30, remapped_regs + mmSCRATCH_UMSK); | ||
749 | |||
750 | /* Set up CIF */ | ||
751 | cif_io.val = defCIF_IO; | ||
752 | writel((u32)(cif_io.val), remapped_regs + mmCIF_IO); | ||
753 | |||
754 | cif_write_dbg.val = readl(remapped_regs + mmCIF_WRITE_DBG); | ||
755 | cif_write_dbg.f.dis_packer_ful_during_rbbm_timeout = 0; | ||
756 | cif_write_dbg.f.en_dword_split_to_rbbm = 1; | ||
757 | cif_write_dbg.f.dis_timeout_during_rbbm = 1; | ||
758 | writel((u32) (cif_write_dbg.val), remapped_regs + mmCIF_WRITE_DBG); | ||
759 | |||
760 | cif_read_dbg.val = readl(remapped_regs + mmCIF_READ_DBG); | ||
761 | cif_read_dbg.f.dis_rd_same_byte_to_trig_fetch = 1; | ||
762 | writel((u32) (cif_read_dbg.val), remapped_regs + mmCIF_READ_DBG); | ||
763 | |||
764 | cif_cntl.val = readl(remapped_regs + mmCIF_CNTL); | ||
765 | cif_cntl.f.dis_system_bits = 1; | ||
766 | cif_cntl.f.dis_mr = 1; | ||
767 | cif_cntl.f.en_wait_to_compensate_dq_prop_dly = 0; | ||
768 | cif_cntl.f.intb_oe = 1; | ||
769 | cif_cntl.f.interrupt_active_high = 1; | ||
770 | writel((u32) (cif_cntl.val), remapped_regs + mmCIF_CNTL); | ||
771 | |||
772 | /* Setup cfgINTF_CNTL and cfgCPU defaults */ | ||
773 | intf_cntl.val = defINTF_CNTL; | ||
774 | intf_cntl.f.ad_inc_a = 1; | ||
775 | intf_cntl.f.ad_inc_b = 1; | ||
776 | intf_cntl.f.rd_data_rdy_a = 0; | ||
777 | intf_cntl.f.rd_data_rdy_b = 0; | ||
778 | writeb((u8) (intf_cntl.val), remapped_base + cfgINTF_CNTL); | ||
779 | |||
780 | cpu_default.val = defCPU_DEFAULTS; | ||
781 | cpu_default.f.access_ind_addr_a = 1; | ||
782 | cpu_default.f.access_ind_addr_b = 1; | ||
783 | cpu_default.f.access_scratch_reg = 1; | ||
784 | cpu_default.f.transition_size = 0; | ||
785 | writeb((u8) (cpu_default.val), remapped_base + cfgCPU_DEFAULTS); | ||
786 | |||
787 | /* set up the apertures */ | ||
788 | writeb((u8) (W100_REG_BASE >> 16), remapped_base + cfgREG_BASE); | ||
789 | |||
790 | cfgreg_base.val = defCFGREG_BASE; | ||
791 | cfgreg_base.f.cfgreg_base = W100_CFG_BASE; | ||
792 | writel((u32) (cfgreg_base.val), remapped_regs + mmCFGREG_BASE); | ||
793 | |||
794 | /* This location is relative to internal w100 addresses */ | ||
795 | writel(0x15FF1000, remapped_regs + mmMC_FB_LOCATION); | ||
796 | |||
797 | mc_ext_mem_loc.val = defMC_EXT_MEM_LOCATION; | ||
798 | mc_ext_mem_loc.f.mc_ext_mem_start = MEM_EXT_BASE_VALUE >> 8; | ||
799 | mc_ext_mem_loc.f.mc_ext_mem_top = MEM_EXT_TOP_VALUE >> 8; | ||
800 | writel((u32) (mc_ext_mem_loc.val), remapped_regs + mmMC_EXT_MEM_LOCATION); | ||
801 | |||
802 | if ((current_par->lcdMode == LCD_MODE_240) || (current_par->lcdMode == LCD_MODE_320)) | ||
803 | w100_InitExtMem(LCD_SHARP_QVGA); | ||
804 | else | ||
805 | w100_InitExtMem(LCD_SHARP_VGA); | ||
806 | |||
807 | wrap_start_dir.val = defWRAP_START_DIR; | ||
808 | wrap_start_dir.f.start_addr = WRAP_BUF_BASE_VALUE >> 1; | ||
809 | writel((u32) (wrap_start_dir.val), remapped_regs + mmWRAP_START_DIR); | ||
810 | |||
811 | wrap_top_dir.val = defWRAP_TOP_DIR; | ||
812 | wrap_top_dir.f.top_addr = WRAP_BUF_TOP_VALUE >> 1; | ||
813 | writel((u32) (wrap_top_dir.val), remapped_regs + mmWRAP_TOP_DIR); | ||
814 | |||
815 | writel((u32) 0x2440, remapped_regs + mmRBBM_CNTL); | ||
816 | } | ||
817 | |||
818 | |||
819 | /* | ||
820 | * Types | ||
821 | */ | ||
822 | |||
823 | struct pll_parm { | ||
824 | u16 freq; /* desired Fout for PLL */ | ||
825 | u8 M; | ||
826 | u8 N_int; | ||
827 | u8 N_fac; | ||
828 | u8 tfgoal; | ||
829 | u8 lock_time; | ||
830 | }; | ||
831 | |||
832 | struct power_state { | ||
833 | union clk_pin_cntl_u clk_pin_cntl; | ||
834 | union pll_ref_fb_div_u pll_ref_fb_div; | ||
835 | union pll_cntl_u pll_cntl; | ||
836 | union sclk_cntl_u sclk_cntl; | ||
837 | union pclk_cntl_u pclk_cntl; | ||
838 | union clk_test_cntl_u clk_test_cntl; | ||
839 | union pwrmgt_cntl_u pwrmgt_cntl; | ||
840 | u32 freq; /* Fout for PLL calibration */ | ||
841 | u8 tf100; /* for pll calibration */ | ||
842 | u8 tf80; /* for pll calibration */ | ||
843 | u8 tf20; /* for pll calibration */ | ||
844 | u8 M; /* for pll calibration */ | ||
845 | u8 N_int; /* for pll calibration */ | ||
846 | u8 N_fac; /* for pll calibration */ | ||
847 | u8 lock_time; /* for pll calibration */ | ||
848 | u8 tfgoal; /* for pll calibration */ | ||
849 | u8 auto_mode; /* hardware auto switch? */ | ||
850 | u8 pwm_mode; /* 0 fast, 1 normal/slow */ | ||
851 | u16 fast_sclk; /* fast clk freq */ | ||
852 | u16 norm_sclk; /* slow clk freq */ | ||
853 | }; | ||
854 | |||
855 | |||
856 | /* | ||
857 | * Global state variables | ||
858 | */ | ||
859 | |||
860 | static struct power_state w100_pwr_state; | ||
861 | |||
862 | /* This table is specific for 12.5MHz ref crystal. */ | ||
863 | static struct pll_parm gPLLTable[] = { | ||
864 | /*freq M N_int N_fac tfgoal lock_time */ | ||
865 | { 50, 0, 1, 0, 0xE0, 56}, /* 50.00 MHz */ | ||
866 | { 75, 0, 5, 0, 0xDE, 37}, /* 75.00 MHz */ | ||
867 | {100, 0, 7, 0, 0xE0, 28}, /* 100.00 MHz */ | ||
868 | {125, 0, 9, 0, 0xE0, 22}, /* 125.00 MHz */ | ||
869 | {150, 0, 11, 0, 0xE0, 17}, /* 150.00 MHz */ | ||
870 | { 0, 0, 0, 0, 0, 0} /* Terminator */ | ||
871 | }; | ||
872 | |||
873 | |||
874 | static u8 w100_pll_get_testcount(u8 testclk_sel) | ||
875 | { | ||
876 | udelay(5); | ||
877 | |||
878 | w100_pwr_state.clk_test_cntl.f.start_check_freq = 0x0; | ||
879 | w100_pwr_state.clk_test_cntl.f.testclk_sel = testclk_sel; | ||
880 | w100_pwr_state.clk_test_cntl.f.tstcount_rst = 0x1; /*reset test count */ | ||
881 | writel((u32) (w100_pwr_state.clk_test_cntl.val), remapped_regs + mmCLK_TEST_CNTL); | ||
882 | w100_pwr_state.clk_test_cntl.f.tstcount_rst = 0x0; | ||
883 | writel((u32) (w100_pwr_state.clk_test_cntl.val), remapped_regs + mmCLK_TEST_CNTL); | ||
884 | |||
885 | w100_pwr_state.clk_test_cntl.f.start_check_freq = 0x1; | ||
886 | writel((u32) (w100_pwr_state.clk_test_cntl.val), remapped_regs + mmCLK_TEST_CNTL); | ||
887 | |||
888 | udelay(20); | ||
889 | |||
890 | w100_pwr_state.clk_test_cntl.val = readl(remapped_regs + mmCLK_TEST_CNTL); | ||
891 | w100_pwr_state.clk_test_cntl.f.start_check_freq = 0x0; | ||
892 | writel((u32) (w100_pwr_state.clk_test_cntl.val), remapped_regs + mmCLK_TEST_CNTL); | ||
893 | |||
894 | return w100_pwr_state.clk_test_cntl.f.test_count; | ||
895 | } | ||
896 | |||
897 | |||
898 | static u8 w100_pll_adjust(void) | ||
899 | { | ||
900 | do { | ||
901 | /* Wai Ming 80 percent of VDD 1.3V gives 1.04V, minimum operating voltage is 1.08V | ||
902 | * therefore, commented out the following lines | ||
903 | * tf80 meant tf100 | ||
904 | * set VCO input = 0.8 * VDD | ||
905 | */ | ||
906 | w100_pwr_state.pll_cntl.f.pll_dactal = 0xd; | ||
907 | writel((u32) (w100_pwr_state.pll_cntl.val), remapped_regs + mmPLL_CNTL); | ||
908 | |||
909 | w100_pwr_state.tf80 = w100_pll_get_testcount(0x1); /* PLLCLK */ | ||
910 | if (w100_pwr_state.tf80 >= (w100_pwr_state.tfgoal)) { | ||
911 | /* set VCO input = 0.2 * VDD */ | ||
912 | w100_pwr_state.pll_cntl.f.pll_dactal = 0x7; | ||
913 | writel((u32) (w100_pwr_state.pll_cntl.val), remapped_regs + mmPLL_CNTL); | ||
914 | |||
915 | w100_pwr_state.tf20 = w100_pll_get_testcount(0x1); /* PLLCLK */ | ||
916 | if (w100_pwr_state.tf20 <= (w100_pwr_state.tfgoal)) | ||
917 | return 1; // Success | ||
918 | |||
919 | if ((w100_pwr_state.pll_cntl.f.pll_vcofr == 0x0) && | ||
920 | ((w100_pwr_state.pll_cntl.f.pll_pvg == 0x7) || | ||
921 | (w100_pwr_state.pll_cntl.f.pll_ioffset == 0x0))) { | ||
922 | /* slow VCO config */ | ||
923 | w100_pwr_state.pll_cntl.f.pll_vcofr = 0x1; | ||
924 | w100_pwr_state.pll_cntl.f.pll_pvg = 0x0; | ||
925 | w100_pwr_state.pll_cntl.f.pll_ioffset = 0x0; | ||
926 | writel((u32) (w100_pwr_state.pll_cntl.val), | ||
927 | remapped_regs + mmPLL_CNTL); | ||
928 | continue; | ||
929 | } | ||
930 | } | ||
931 | if ((w100_pwr_state.pll_cntl.f.pll_ioffset) < 0x3) { | ||
932 | w100_pwr_state.pll_cntl.f.pll_ioffset += 0x1; | ||
933 | writel((u32) (w100_pwr_state.pll_cntl.val), remapped_regs + mmPLL_CNTL); | ||
934 | continue; | ||
935 | } | ||
936 | if ((w100_pwr_state.pll_cntl.f.pll_pvg) < 0x7) { | ||
937 | w100_pwr_state.pll_cntl.f.pll_ioffset = 0x0; | ||
938 | w100_pwr_state.pll_cntl.f.pll_pvg += 0x1; | ||
939 | writel((u32) (w100_pwr_state.pll_cntl.val), remapped_regs + mmPLL_CNTL); | ||
940 | continue; | ||
941 | } | ||
942 | return 0; // error | ||
943 | } while(1); | ||
944 | } | ||
945 | |||
946 | |||
947 | /* | ||
948 | * w100_pll_calibration | ||
949 | * freq = target frequency of the PLL | ||
950 | * (note: crystal = 14.3MHz) | ||
951 | */ | ||
952 | static u8 w100_pll_calibration(u32 freq) | ||
953 | { | ||
954 | u8 status; | ||
955 | |||
956 | /* initial setting */ | ||
957 | w100_pwr_state.pll_cntl.f.pll_pwdn = 0x0; /* power down */ | ||
958 | w100_pwr_state.pll_cntl.f.pll_reset = 0x0; /* not reset */ | ||
959 | w100_pwr_state.pll_cntl.f.pll_tcpoff = 0x1; /* Hi-Z */ | ||
960 | w100_pwr_state.pll_cntl.f.pll_pvg = 0x0; /* VCO gain = 0 */ | ||
961 | w100_pwr_state.pll_cntl.f.pll_vcofr = 0x0; /* VCO frequency range control = off */ | ||
962 | w100_pwr_state.pll_cntl.f.pll_ioffset = 0x0; /* current offset inside VCO = 0 */ | ||
963 | w100_pwr_state.pll_cntl.f.pll_ring_off = 0x0; | ||
964 | writel((u32) (w100_pwr_state.pll_cntl.val), remapped_regs + mmPLL_CNTL); | ||
965 | |||
966 | /* check for (tf80 >= tfgoal) && (tf20 =< tfgoal) */ | ||
967 | if ((w100_pwr_state.tf80 < w100_pwr_state.tfgoal) || (w100_pwr_state.tf20 > w100_pwr_state.tfgoal)) { | ||
968 | status=w100_pll_adjust(); | ||
969 | } | ||
970 | /* PLL Reset And Lock */ | ||
971 | |||
972 | /* set VCO input = 0.5 * VDD */ | ||
973 | w100_pwr_state.pll_cntl.f.pll_dactal = 0xa; | ||
974 | writel((u32) (w100_pwr_state.pll_cntl.val), remapped_regs + mmPLL_CNTL); | ||
975 | |||
976 | /* reset time */ | ||
977 | udelay(1); | ||
978 | |||
979 | /* enable charge pump */ | ||
980 | w100_pwr_state.pll_cntl.f.pll_tcpoff = 0x0; /* normal */ | ||
981 | writel((u32) (w100_pwr_state.pll_cntl.val), remapped_regs + mmPLL_CNTL); | ||
982 | |||
983 | /* set VCO input = Hi-Z */ | ||
984 | /* disable DAC */ | ||
985 | w100_pwr_state.pll_cntl.f.pll_dactal = 0x0; | ||
986 | writel((u32) (w100_pwr_state.pll_cntl.val), remapped_regs + mmPLL_CNTL); | ||
987 | |||
988 | /* lock time */ | ||
989 | udelay(400); /* delay 400 us */ | ||
990 | |||
991 | /* PLL locked */ | ||
992 | |||
993 | w100_pwr_state.sclk_cntl.f.sclk_src_sel = 0x1; /* PLL clock */ | ||
994 | writel((u32) (w100_pwr_state.sclk_cntl.val), remapped_regs + mmSCLK_CNTL); | ||
995 | |||
996 | w100_pwr_state.tf100 = w100_pll_get_testcount(0x1); /* PLLCLK */ | ||
997 | |||
998 | return status; | ||
999 | } | ||
1000 | |||
1001 | |||
1002 | static u8 w100_pll_set_clk(void) | ||
1003 | { | ||
1004 | u8 status; | ||
1005 | |||
1006 | if (w100_pwr_state.auto_mode == 1) /* auto mode */ | ||
1007 | { | ||
1008 | w100_pwr_state.pwrmgt_cntl.f.pwm_fast_noml_hw_en = 0x0; /* disable fast to normal */ | ||
1009 | w100_pwr_state.pwrmgt_cntl.f.pwm_noml_fast_hw_en = 0x0; /* disable normal to fast */ | ||
1010 | writel((u32) (w100_pwr_state.pwrmgt_cntl.val), remapped_regs + mmPWRMGT_CNTL); | ||
1011 | } | ||
1012 | |||
1013 | w100_pwr_state.sclk_cntl.f.sclk_src_sel = 0x0; /* crystal clock */ | ||
1014 | writel((u32) (w100_pwr_state.sclk_cntl.val), remapped_regs + mmSCLK_CNTL); | ||
1015 | |||
1016 | w100_pwr_state.pll_ref_fb_div.f.pll_ref_div = w100_pwr_state.M; | ||
1017 | w100_pwr_state.pll_ref_fb_div.f.pll_fb_div_int = w100_pwr_state.N_int; | ||
1018 | w100_pwr_state.pll_ref_fb_div.f.pll_fb_div_frac = w100_pwr_state.N_fac; | ||
1019 | w100_pwr_state.pll_ref_fb_div.f.pll_lock_time = w100_pwr_state.lock_time; | ||
1020 | writel((u32) (w100_pwr_state.pll_ref_fb_div.val), remapped_regs + mmPLL_REF_FB_DIV); | ||
1021 | |||
1022 | w100_pwr_state.pwrmgt_cntl.f.pwm_mode_req = 0; | ||
1023 | writel((u32) (w100_pwr_state.pwrmgt_cntl.val), remapped_regs + mmPWRMGT_CNTL); | ||
1024 | |||
1025 | status = w100_pll_calibration (w100_pwr_state.freq); | ||
1026 | |||
1027 | if (w100_pwr_state.auto_mode == 1) /* auto mode */ | ||
1028 | { | ||
1029 | w100_pwr_state.pwrmgt_cntl.f.pwm_fast_noml_hw_en = 0x1; /* reenable fast to normal */ | ||
1030 | w100_pwr_state.pwrmgt_cntl.f.pwm_noml_fast_hw_en = 0x1; /* reenable normal to fast */ | ||
1031 | writel((u32) (w100_pwr_state.pwrmgt_cntl.val), remapped_regs + mmPWRMGT_CNTL); | ||
1032 | } | ||
1033 | return status; | ||
1034 | } | ||
1035 | |||
1036 | |||
1037 | /* assume reference crystal clk is 12.5MHz, | ||
1038 | * and that doubling is not enabled. | ||
1039 | * | ||
1040 | * Freq = 12 == 12.5MHz. | ||
1041 | */ | ||
1042 | static u16 w100_set_slowsysclk(u16 freq) | ||
1043 | { | ||
1044 | if (w100_pwr_state.norm_sclk == freq) | ||
1045 | return freq; | ||
1046 | |||
1047 | if (w100_pwr_state.auto_mode == 1) /* auto mode */ | ||
1048 | return 0; | ||
1049 | |||
1050 | if (freq == 12) { | ||
1051 | w100_pwr_state.norm_sclk = freq; | ||
1052 | w100_pwr_state.sclk_cntl.f.sclk_post_div_slow = 0x0; /* Pslow = 1 */ | ||
1053 | w100_pwr_state.sclk_cntl.f.sclk_src_sel = 0x0; /* crystal src */ | ||
1054 | |||
1055 | writel((u32) (w100_pwr_state.sclk_cntl.val), remapped_regs + mmSCLK_CNTL); | ||
1056 | |||
1057 | w100_pwr_state.clk_pin_cntl.f.xtalin_pm_en = 0x1; | ||
1058 | writel((u32) (w100_pwr_state.clk_pin_cntl.val), remapped_regs + mmCLK_PIN_CNTL); | ||
1059 | |||
1060 | w100_pwr_state.pwrmgt_cntl.f.pwm_enable = 0x1; | ||
1061 | w100_pwr_state.pwrmgt_cntl.f.pwm_mode_req = 0x1; | ||
1062 | writel((u32) (w100_pwr_state.pwrmgt_cntl.val), remapped_regs + mmPWRMGT_CNTL); | ||
1063 | w100_pwr_state.pwm_mode = 1; /* normal mode */ | ||
1064 | return freq; | ||
1065 | } else | ||
1066 | return 0; | ||
1067 | } | ||
1068 | |||
1069 | |||
1070 | static u16 w100_set_fastsysclk(u16 freq) | ||
1071 | { | ||
1072 | u16 pll_freq; | ||
1073 | int i; | ||
1074 | |||
1075 | while(1) { | ||
1076 | pll_freq = (u16) (freq * (w100_pwr_state.sclk_cntl.f.sclk_post_div_fast + 1)); | ||
1077 | i = 0; | ||
1078 | do { | ||
1079 | if (pll_freq == gPLLTable[i].freq) { | ||
1080 | w100_pwr_state.freq = gPLLTable[i].freq * 1000000; | ||
1081 | w100_pwr_state.M = gPLLTable[i].M; | ||
1082 | w100_pwr_state.N_int = gPLLTable[i].N_int; | ||
1083 | w100_pwr_state.N_fac = gPLLTable[i].N_fac; | ||
1084 | w100_pwr_state.tfgoal = gPLLTable[i].tfgoal; | ||
1085 | w100_pwr_state.lock_time = gPLLTable[i].lock_time; | ||
1086 | w100_pwr_state.tf20 = 0xff; /* set highest */ | ||
1087 | w100_pwr_state.tf80 = 0x00; /* set lowest */ | ||
1088 | |||
1089 | w100_pll_set_clk(); | ||
1090 | w100_pwr_state.pwm_mode = 0; /* fast mode */ | ||
1091 | w100_pwr_state.fast_sclk = freq; | ||
1092 | return freq; | ||
1093 | } | ||
1094 | i++; | ||
1095 | } while(gPLLTable[i].freq); | ||
1096 | |||
1097 | if (w100_pwr_state.auto_mode == 1) | ||
1098 | break; | ||
1099 | |||
1100 | if (w100_pwr_state.sclk_cntl.f.sclk_post_div_fast == 0) | ||
1101 | break; | ||
1102 | |||
1103 | w100_pwr_state.sclk_cntl.f.sclk_post_div_fast -= 1; | ||
1104 | writel((u32) (w100_pwr_state.sclk_cntl.val), remapped_regs + mmSCLK_CNTL); | ||
1105 | } | ||
1106 | return 0; | ||
1107 | } | ||
1108 | |||
1109 | |||
1110 | /* Set up an initial state. Some values/fields set | ||
1111 | here will be overwritten. */ | ||
1112 | static void w100_pwm_setup(void) | ||
1113 | { | ||
1114 | w100_pwr_state.clk_pin_cntl.f.osc_en = 0x1; | ||
1115 | w100_pwr_state.clk_pin_cntl.f.osc_gain = 0x1f; | ||
1116 | w100_pwr_state.clk_pin_cntl.f.dont_use_xtalin = 0x0; | ||
1117 | w100_pwr_state.clk_pin_cntl.f.xtalin_pm_en = 0x0; | ||
1118 | w100_pwr_state.clk_pin_cntl.f.xtalin_dbl_en = 0x0; /* no freq doubling */ | ||
1119 | w100_pwr_state.clk_pin_cntl.f.cg_debug = 0x0; | ||
1120 | writel((u32) (w100_pwr_state.clk_pin_cntl.val), remapped_regs + mmCLK_PIN_CNTL); | ||
1121 | |||
1122 | w100_pwr_state.sclk_cntl.f.sclk_src_sel = 0x0; /* Crystal Clk */ | ||
1123 | w100_pwr_state.sclk_cntl.f.sclk_post_div_fast = 0x0; /* Pfast = 1 */ | ||
1124 | w100_pwr_state.sclk_cntl.f.sclk_clkon_hys = 0x3; | ||
1125 | w100_pwr_state.sclk_cntl.f.sclk_post_div_slow = 0x0; /* Pslow = 1 */ | ||
1126 | w100_pwr_state.sclk_cntl.f.disp_cg_ok2switch_en = 0x0; | ||
1127 | w100_pwr_state.sclk_cntl.f.sclk_force_reg = 0x0; /* Dynamic */ | ||
1128 | w100_pwr_state.sclk_cntl.f.sclk_force_disp = 0x0; /* Dynamic */ | ||
1129 | w100_pwr_state.sclk_cntl.f.sclk_force_mc = 0x0; /* Dynamic */ | ||
1130 | w100_pwr_state.sclk_cntl.f.sclk_force_extmc = 0x0; /* Dynamic */ | ||
1131 | w100_pwr_state.sclk_cntl.f.sclk_force_cp = 0x0; /* Dynamic */ | ||
1132 | w100_pwr_state.sclk_cntl.f.sclk_force_e2 = 0x0; /* Dynamic */ | ||
1133 | w100_pwr_state.sclk_cntl.f.sclk_force_e3 = 0x0; /* Dynamic */ | ||
1134 | w100_pwr_state.sclk_cntl.f.sclk_force_idct = 0x0; /* Dynamic */ | ||
1135 | w100_pwr_state.sclk_cntl.f.sclk_force_bist = 0x0; /* Dynamic */ | ||
1136 | w100_pwr_state.sclk_cntl.f.busy_extend_cp = 0x0; | ||
1137 | w100_pwr_state.sclk_cntl.f.busy_extend_e2 = 0x0; | ||
1138 | w100_pwr_state.sclk_cntl.f.busy_extend_e3 = 0x0; | ||
1139 | w100_pwr_state.sclk_cntl.f.busy_extend_idct = 0x0; | ||
1140 | writel((u32) (w100_pwr_state.sclk_cntl.val), remapped_regs + mmSCLK_CNTL); | ||
1141 | |||
1142 | w100_pwr_state.pclk_cntl.f.pclk_src_sel = 0x0; /* Crystal Clk */ | ||
1143 | w100_pwr_state.pclk_cntl.f.pclk_post_div = 0x1; /* P = 2 */ | ||
1144 | w100_pwr_state.pclk_cntl.f.pclk_force_disp = 0x0; /* Dynamic */ | ||
1145 | writel((u32) (w100_pwr_state.pclk_cntl.val), remapped_regs + mmPCLK_CNTL); | ||
1146 | |||
1147 | w100_pwr_state.pll_ref_fb_div.f.pll_ref_div = 0x0; /* M = 1 */ | ||
1148 | w100_pwr_state.pll_ref_fb_div.f.pll_fb_div_int = 0x0; /* N = 1.0 */ | ||
1149 | w100_pwr_state.pll_ref_fb_div.f.pll_fb_div_frac = 0x0; | ||
1150 | w100_pwr_state.pll_ref_fb_div.f.pll_reset_time = 0x5; | ||
1151 | w100_pwr_state.pll_ref_fb_div.f.pll_lock_time = 0xff; | ||
1152 | writel((u32) (w100_pwr_state.pll_ref_fb_div.val), remapped_regs + mmPLL_REF_FB_DIV); | ||
1153 | |||
1154 | w100_pwr_state.pll_cntl.f.pll_pwdn = 0x1; | ||
1155 | w100_pwr_state.pll_cntl.f.pll_reset = 0x1; | ||
1156 | w100_pwr_state.pll_cntl.f.pll_pm_en = 0x0; | ||
1157 | w100_pwr_state.pll_cntl.f.pll_mode = 0x0; /* uses VCO clock */ | ||
1158 | w100_pwr_state.pll_cntl.f.pll_refclk_sel = 0x0; | ||
1159 | w100_pwr_state.pll_cntl.f.pll_fbclk_sel = 0x0; | ||
1160 | w100_pwr_state.pll_cntl.f.pll_tcpoff = 0x0; | ||
1161 | w100_pwr_state.pll_cntl.f.pll_pcp = 0x4; | ||
1162 | w100_pwr_state.pll_cntl.f.pll_pvg = 0x0; | ||
1163 | w100_pwr_state.pll_cntl.f.pll_vcofr = 0x0; | ||
1164 | w100_pwr_state.pll_cntl.f.pll_ioffset = 0x0; | ||
1165 | w100_pwr_state.pll_cntl.f.pll_pecc_mode = 0x0; | ||
1166 | w100_pwr_state.pll_cntl.f.pll_pecc_scon = 0x0; | ||
1167 | w100_pwr_state.pll_cntl.f.pll_dactal = 0x0; /* Hi-Z */ | ||
1168 | w100_pwr_state.pll_cntl.f.pll_cp_clip = 0x3; | ||
1169 | w100_pwr_state.pll_cntl.f.pll_conf = 0x2; | ||
1170 | w100_pwr_state.pll_cntl.f.pll_mbctrl = 0x2; | ||
1171 | w100_pwr_state.pll_cntl.f.pll_ring_off = 0x0; | ||
1172 | writel((u32) (w100_pwr_state.pll_cntl.val), remapped_regs + mmPLL_CNTL); | ||
1173 | |||
1174 | w100_pwr_state.clk_test_cntl.f.testclk_sel = 0x1; /* PLLCLK (for testing) */ | ||
1175 | w100_pwr_state.clk_test_cntl.f.start_check_freq = 0x0; | ||
1176 | w100_pwr_state.clk_test_cntl.f.tstcount_rst = 0x0; | ||
1177 | writel((u32) (w100_pwr_state.clk_test_cntl.val), remapped_regs + mmCLK_TEST_CNTL); | ||
1178 | |||
1179 | w100_pwr_state.pwrmgt_cntl.f.pwm_enable = 0x0; | ||
1180 | w100_pwr_state.pwrmgt_cntl.f.pwm_mode_req = 0x1; /* normal mode (0, 1, 3) */ | ||
1181 | w100_pwr_state.pwrmgt_cntl.f.pwm_wakeup_cond = 0x0; | ||
1182 | w100_pwr_state.pwrmgt_cntl.f.pwm_fast_noml_hw_en = 0x0; | ||
1183 | w100_pwr_state.pwrmgt_cntl.f.pwm_noml_fast_hw_en = 0x0; | ||
1184 | w100_pwr_state.pwrmgt_cntl.f.pwm_fast_noml_cond = 0x1; /* PM4,ENG */ | ||
1185 | w100_pwr_state.pwrmgt_cntl.f.pwm_noml_fast_cond = 0x1; /* PM4,ENG */ | ||
1186 | w100_pwr_state.pwrmgt_cntl.f.pwm_idle_timer = 0xFF; | ||
1187 | w100_pwr_state.pwrmgt_cntl.f.pwm_busy_timer = 0xFF; | ||
1188 | writel((u32) (w100_pwr_state.pwrmgt_cntl.val), remapped_regs + mmPWRMGT_CNTL); | ||
1189 | |||
1190 | w100_pwr_state.auto_mode = 0; /* manual mode */ | ||
1191 | w100_pwr_state.pwm_mode = 1; /* normal mode (0, 1, 2) */ | ||
1192 | w100_pwr_state.freq = 50000000; /* 50 MHz */ | ||
1193 | w100_pwr_state.M = 3; /* M = 4 */ | ||
1194 | w100_pwr_state.N_int = 6; /* N = 7.0 */ | ||
1195 | w100_pwr_state.N_fac = 0; | ||
1196 | w100_pwr_state.tfgoal = 0xE0; | ||
1197 | w100_pwr_state.lock_time = 56; | ||
1198 | w100_pwr_state.tf20 = 0xff; /* set highest */ | ||
1199 | w100_pwr_state.tf80 = 0x00; /* set lowest */ | ||
1200 | w100_pwr_state.tf100 = 0x00; /* set lowest */ | ||
1201 | w100_pwr_state.fast_sclk = 50; /* 50.0 MHz */ | ||
1202 | w100_pwr_state.norm_sclk = 12; /* 12.5 MHz */ | ||
1203 | } | ||
1204 | |||
1205 | |||
1206 | static void w100_init_sharp_lcd(u32 mode) | ||
1207 | { | ||
1208 | u32 temp32; | ||
1209 | union disp_db_buf_cntl_wr_u disp_db_buf_wr_cntl; | ||
1210 | |||
1211 | /* Prevent display updates */ | ||
1212 | disp_db_buf_wr_cntl.f.db_buf_cntl = 0x1e; | ||
1213 | disp_db_buf_wr_cntl.f.update_db_buf = 0; | ||
1214 | disp_db_buf_wr_cntl.f.en_db_buf = 0; | ||
1215 | writel((u32) (disp_db_buf_wr_cntl.val), remapped_regs + mmDISP_DB_BUF_CNTL); | ||
1216 | |||
1217 | switch(mode) { | ||
1218 | case LCD_SHARP_QVGA: | ||
1219 | w100_set_slowsysclk(12); /* use crystal -- 12.5MHz */ | ||
1220 | /* not use PLL */ | ||
1221 | |||
1222 | writel(0x7FFF8000, remapped_regs + mmMC_EXT_MEM_LOCATION); | ||
1223 | writel(0x85FF8000, remapped_regs + mmMC_FB_LOCATION); | ||
1224 | writel(0x00000003, remapped_regs + mmLCD_FORMAT); | ||
1225 | writel(0x00CF1C06, remapped_regs + mmGRAPHIC_CTRL); | ||
1226 | writel(0x01410145, remapped_regs + mmCRTC_TOTAL); | ||
1227 | writel(0x01170027, remapped_regs + mmACTIVE_H_DISP); | ||
1228 | writel(0x01410001, remapped_regs + mmACTIVE_V_DISP); | ||
1229 | writel(0x01170027, remapped_regs + mmGRAPHIC_H_DISP); | ||
1230 | writel(0x01410001, remapped_regs + mmGRAPHIC_V_DISP); | ||
1231 | writel(0x81170027, remapped_regs + mmCRTC_SS); | ||
1232 | writel(0xA0140000, remapped_regs + mmCRTC_LS); | ||
1233 | writel(0x00400008, remapped_regs + mmCRTC_REV); | ||
1234 | writel(0xA0000000, remapped_regs + mmCRTC_DCLK); | ||
1235 | writel(0xC0140014, remapped_regs + mmCRTC_GS); | ||
1236 | writel(0x00010141, remapped_regs + mmCRTC_VPOS_GS); | ||
1237 | writel(0x8015010F, remapped_regs + mmCRTC_GCLK); | ||
1238 | writel(0x80100110, remapped_regs + mmCRTC_GOE); | ||
1239 | writel(0x00000000, remapped_regs + mmCRTC_FRAME); | ||
1240 | writel(0x00000000, remapped_regs + mmCRTC_FRAME_VPOS); | ||
1241 | writel(0x01CC0000, remapped_regs + mmLCDD_CNTL1); | ||
1242 | writel(0x0003FFFF, remapped_regs + mmLCDD_CNTL2); | ||
1243 | writel(0x00FFFF0D, remapped_regs + mmGENLCD_CNTL1); | ||
1244 | writel(0x003F3003, remapped_regs + mmGENLCD_CNTL2); | ||
1245 | writel(0x00000000, remapped_regs + mmCRTC_DEFAULT_COUNT); | ||
1246 | writel(0x0000FF00, remapped_regs + mmLCD_BACKGROUND_COLOR); | ||
1247 | writel(0x000102aa, remapped_regs + mmGENLCD_CNTL3); | ||
1248 | writel(0x00800000, remapped_regs + mmGRAPHIC_OFFSET); | ||
1249 | writel(0x000001e0, remapped_regs + mmGRAPHIC_PITCH); | ||
1250 | writel(0x000000bf, remapped_regs + mmGPIO_DATA); | ||
1251 | writel(0x03c0feff, remapped_regs + mmGPIO_CNTL2); | ||
1252 | writel(0x00000000, remapped_regs + mmGPIO_CNTL1); | ||
1253 | writel(0x41060010, remapped_regs + mmCRTC_PS1_ACTIVE); | ||
1254 | break; | ||
1255 | case LCD_SHARP_VGA: | ||
1256 | w100_set_slowsysclk(12); /* use crystal -- 12.5MHz */ | ||
1257 | w100_set_fastsysclk(current_par->fastsysclk_mode); /* use PLL -- 75.0MHz */ | ||
1258 | w100_pwr_state.pclk_cntl.f.pclk_src_sel = 0x1; | ||
1259 | w100_pwr_state.pclk_cntl.f.pclk_post_div = 0x2; | ||
1260 | writel((u32) (w100_pwr_state.pclk_cntl.val), remapped_regs + mmPCLK_CNTL); | ||
1261 | writel(0x15FF1000, remapped_regs + mmMC_FB_LOCATION); | ||
1262 | writel(0x9FFF8000, remapped_regs + mmMC_EXT_MEM_LOCATION); | ||
1263 | writel(0x00000003, remapped_regs + mmLCD_FORMAT); | ||
1264 | writel(0x00DE1D66, remapped_regs + mmGRAPHIC_CTRL); | ||
1265 | |||
1266 | writel(0x0283028B, remapped_regs + mmCRTC_TOTAL); | ||
1267 | writel(0x02360056, remapped_regs + mmACTIVE_H_DISP); | ||
1268 | writel(0x02830003, remapped_regs + mmACTIVE_V_DISP); | ||
1269 | writel(0x02360056, remapped_regs + mmGRAPHIC_H_DISP); | ||
1270 | writel(0x02830003, remapped_regs + mmGRAPHIC_V_DISP); | ||
1271 | writel(0x82360056, remapped_regs + mmCRTC_SS); | ||
1272 | writel(0xA0280000, remapped_regs + mmCRTC_LS); | ||
1273 | writel(0x00400008, remapped_regs + mmCRTC_REV); | ||
1274 | writel(0xA0000000, remapped_regs + mmCRTC_DCLK); | ||
1275 | writel(0x80280028, remapped_regs + mmCRTC_GS); | ||
1276 | writel(0x02830002, remapped_regs + mmCRTC_VPOS_GS); | ||
1277 | writel(0x8015010F, remapped_regs + mmCRTC_GCLK); | ||
1278 | writel(0x80100110, remapped_regs + mmCRTC_GOE); | ||
1279 | writel(0x00000000, remapped_regs + mmCRTC_FRAME); | ||
1280 | writel(0x00000000, remapped_regs + mmCRTC_FRAME_VPOS); | ||
1281 | writel(0x01CC0000, remapped_regs + mmLCDD_CNTL1); | ||
1282 | writel(0x0003FFFF, remapped_regs + mmLCDD_CNTL2); | ||
1283 | writel(0x00FFFF0D, remapped_regs + mmGENLCD_CNTL1); | ||
1284 | writel(0x003F3003, remapped_regs + mmGENLCD_CNTL2); | ||
1285 | writel(0x00000000, remapped_regs + mmCRTC_DEFAULT_COUNT); | ||
1286 | writel(0x0000FF00, remapped_regs + mmLCD_BACKGROUND_COLOR); | ||
1287 | writel(0x000102aa, remapped_regs + mmGENLCD_CNTL3); | ||
1288 | writel(0x00800000, remapped_regs + mmGRAPHIC_OFFSET); | ||
1289 | writel(0x000003C0, remapped_regs + mmGRAPHIC_PITCH); | ||
1290 | writel(0x000000bf, remapped_regs + mmGPIO_DATA); | ||
1291 | writel(0x03c0feff, remapped_regs + mmGPIO_CNTL2); | ||
1292 | writel(0x00000000, remapped_regs + mmGPIO_CNTL1); | ||
1293 | writel(0x41060010, remapped_regs + mmCRTC_PS1_ACTIVE); | ||
1294 | break; | ||
1295 | default: | ||
1296 | break; | ||
1297 | } | ||
1298 | |||
1299 | /* Hack for overlay in ext memory */ | ||
1300 | temp32 = readl(remapped_regs + mmDISP_DEBUG2); | ||
1301 | temp32 |= 0xc0000000; | ||
1302 | writel(temp32, remapped_regs + mmDISP_DEBUG2); | ||
1303 | |||
1304 | /* Re-enable display updates */ | ||
1305 | disp_db_buf_wr_cntl.f.db_buf_cntl = 0x1e; | ||
1306 | disp_db_buf_wr_cntl.f.update_db_buf = 1; | ||
1307 | disp_db_buf_wr_cntl.f.en_db_buf = 1; | ||
1308 | writel((u32) (disp_db_buf_wr_cntl.val), remapped_regs + mmDISP_DB_BUF_CNTL); | ||
1309 | } | ||
1310 | |||
1311 | |||
1312 | static void w100_set_vga_rotation_regs(u16 divider, unsigned long ctrl, unsigned long offset, unsigned long pitch) | ||
1313 | { | ||
1314 | w100_pwr_state.pclk_cntl.f.pclk_src_sel = 0x1; | ||
1315 | w100_pwr_state.pclk_cntl.f.pclk_post_div = divider; | ||
1316 | writel((u32) (w100_pwr_state.pclk_cntl.val), remapped_regs + mmPCLK_CNTL); | ||
1317 | |||
1318 | writel(ctrl, remapped_regs + mmGRAPHIC_CTRL); | ||
1319 | writel(offset, remapped_regs + mmGRAPHIC_OFFSET); | ||
1320 | writel(pitch, remapped_regs + mmGRAPHIC_PITCH); | ||
1321 | |||
1322 | /* Re-enable display updates */ | ||
1323 | writel(0x0000007b, remapped_regs + mmDISP_DB_BUF_CNTL); | ||
1324 | } | ||
1325 | |||
1326 | |||
1327 | static void w100_init_vga_rotation(u16 deg) | ||
1328 | { | ||
1329 | switch(deg) { | ||
1330 | case 0: | ||
1331 | w100_set_vga_rotation_regs(0x02, 0x00DE1D66, 0x00800000, 0x000003c0); | ||
1332 | break; | ||
1333 | case 90: | ||
1334 | w100_set_vga_rotation_regs(0x06, 0x00DE1D0e, 0x00895b00, 0x00000500); | ||
1335 | break; | ||
1336 | case 180: | ||
1337 | w100_set_vga_rotation_regs(0x02, 0x00DE1D7e, 0x00895ffc, 0x000003c0); | ||
1338 | break; | ||
1339 | case 270: | ||
1340 | w100_set_vga_rotation_regs(0x06, 0x00DE1D16, 0x008004fc, 0x00000500); | ||
1341 | break; | ||
1342 | default: | ||
1343 | /* not-support */ | ||
1344 | break; | ||
1345 | } | ||
1346 | } | ||
1347 | |||
1348 | |||
1349 | static void w100_set_qvga_rotation_regs(unsigned long ctrl, unsigned long offset, unsigned long pitch) | ||
1350 | { | ||
1351 | writel(ctrl, remapped_regs + mmGRAPHIC_CTRL); | ||
1352 | writel(offset, remapped_regs + mmGRAPHIC_OFFSET); | ||
1353 | writel(pitch, remapped_regs + mmGRAPHIC_PITCH); | ||
1354 | |||
1355 | /* Re-enable display updates */ | ||
1356 | writel(0x0000007b, remapped_regs + mmDISP_DB_BUF_CNTL); | ||
1357 | } | ||
1358 | |||
1359 | |||
1360 | static void w100_init_qvga_rotation(u16 deg) | ||
1361 | { | ||
1362 | switch(deg) { | ||
1363 | case 0: | ||
1364 | w100_set_qvga_rotation_regs(0x00d41c06, 0x00800000, 0x000001e0); | ||
1365 | break; | ||
1366 | case 90: | ||
1367 | w100_set_qvga_rotation_regs(0x00d41c0E, 0x00825580, 0x00000280); | ||
1368 | break; | ||
1369 | case 180: | ||
1370 | w100_set_qvga_rotation_regs(0x00d41c1e, 0x008257fc, 0x000001e0); | ||
1371 | break; | ||
1372 | case 270: | ||
1373 | w100_set_qvga_rotation_regs(0x00d41c16, 0x0080027c, 0x00000280); | ||
1374 | break; | ||
1375 | default: | ||
1376 | /* not-support */ | ||
1377 | break; | ||
1378 | } | ||
1379 | } | ||
1380 | |||
1381 | |||
1382 | static void w100_suspend(u32 mode) | ||
1383 | { | ||
1384 | u32 val; | ||
1385 | |||
1386 | writel(0x7FFF8000, remapped_regs + mmMC_EXT_MEM_LOCATION); | ||
1387 | writel(0x00FF0000, remapped_regs + mmMC_PERF_MON_CNTL); | ||
1388 | |||
1389 | val = readl(remapped_regs + mmMEM_EXT_TIMING_CNTL); | ||
1390 | val &= ~(0x00100000); /* bit20=0 */ | ||
1391 | val |= 0xFF000000; /* bit31:24=0xff */ | ||
1392 | writel(val, remapped_regs + mmMEM_EXT_TIMING_CNTL); | ||
1393 | |||
1394 | val = readl(remapped_regs + mmMEM_EXT_CNTL); | ||
1395 | val &= ~(0x00040000); /* bit18=0 */ | ||
1396 | val |= 0x00080000; /* bit19=1 */ | ||
1397 | writel(val, remapped_regs + mmMEM_EXT_CNTL); | ||
1398 | |||
1399 | udelay(1); /* wait 1us */ | ||
1400 | |||
1401 | if (mode == W100_SUSPEND_EXTMEM) { | ||
1402 | |||
1403 | /* CKE: Tri-State */ | ||
1404 | val = readl(remapped_regs + mmMEM_EXT_CNTL); | ||
1405 | val |= 0x40000000; /* bit30=1 */ | ||
1406 | writel(val, remapped_regs + mmMEM_EXT_CNTL); | ||
1407 | |||
1408 | /* CLK: Stop */ | ||
1409 | val = readl(remapped_regs + mmMEM_EXT_CNTL); | ||
1410 | val &= ~(0x00000001); /* bit0=0 */ | ||
1411 | writel(val, remapped_regs + mmMEM_EXT_CNTL); | ||
1412 | } else { | ||
1413 | |||
1414 | writel(0x00000000, remapped_regs + mmSCLK_CNTL); | ||
1415 | writel(0x000000BF, remapped_regs + mmCLK_PIN_CNTL); | ||
1416 | writel(0x00000015, remapped_regs + mmPWRMGT_CNTL); | ||
1417 | |||
1418 | udelay(5); | ||
1419 | |||
1420 | val = readl(remapped_regs + mmPLL_CNTL); | ||
1421 | val |= 0x00000004; /* bit2=1 */ | ||
1422 | writel(val, remapped_regs + mmPLL_CNTL); | ||
1423 | writel(0x0000001d, remapped_regs + mmPWRMGT_CNTL); | ||
1424 | } | ||
1425 | } | ||
1426 | |||
1427 | |||
1428 | static void w100_resume(void) | ||
1429 | { | ||
1430 | u32 temp32; | ||
1431 | |||
1432 | w100_hw_init(); | ||
1433 | w100_pwm_setup(); | ||
1434 | |||
1435 | temp32 = readl(remapped_regs + mmDISP_DEBUG2); | ||
1436 | temp32 &= 0xff7fffff; | ||
1437 | temp32 |= 0x00800000; | ||
1438 | writel(temp32, remapped_regs + mmDISP_DEBUG2); | ||
1439 | |||
1440 | if (current_par->lcdMode == LCD_MODE_480 || current_par->lcdMode == LCD_MODE_640) { | ||
1441 | w100_init_sharp_lcd(LCD_SHARP_VGA); | ||
1442 | if (current_par->lcdMode == LCD_MODE_640) { | ||
1443 | w100_init_vga_rotation(current_par->rotation_flag ? 270 : 90); | ||
1444 | } | ||
1445 | } else { | ||
1446 | w100_init_sharp_lcd(LCD_SHARP_QVGA); | ||
1447 | if (current_par->lcdMode == LCD_MODE_320) { | ||
1448 | w100_init_qvga_rotation(current_par->rotation_flag ? 270 : 90); | ||
1449 | } | ||
1450 | } | ||
1451 | } | ||
1452 | |||
1453 | |||
1454 | static void w100_vsync(void) | ||
1455 | { | ||
1456 | u32 tmp; | ||
1457 | int timeout = 30000; /* VSync timeout = 30[ms] > 16.8[ms] */ | ||
1458 | |||
1459 | tmp = readl(remapped_regs + mmACTIVE_V_DISP); | ||
1460 | |||
1461 | /* set vline pos */ | ||
1462 | writel((tmp >> 16) & 0x3ff, remapped_regs + mmDISP_INT_CNTL); | ||
1463 | |||
1464 | /* disable vline irq */ | ||
1465 | tmp = readl(remapped_regs + mmGEN_INT_CNTL); | ||
1466 | |||
1467 | tmp &= ~0x00000002; | ||
1468 | writel(tmp, remapped_regs + mmGEN_INT_CNTL); | ||
1469 | |||
1470 | /* clear vline irq status */ | ||
1471 | writel(0x00000002, remapped_regs + mmGEN_INT_STATUS); | ||
1472 | |||
1473 | /* enable vline irq */ | ||
1474 | writel((tmp | 0x00000002), remapped_regs + mmGEN_INT_CNTL); | ||
1475 | |||
1476 | /* clear vline irq status */ | ||
1477 | writel(0x00000002, remapped_regs + mmGEN_INT_STATUS); | ||
1478 | |||
1479 | while(timeout > 0) { | ||
1480 | if (readl(remapped_regs + mmGEN_INT_STATUS) & 0x00000002) | ||
1481 | break; | ||
1482 | udelay(1); | ||
1483 | timeout--; | ||
1484 | } | ||
1485 | |||
1486 | /* disable vline irq */ | ||
1487 | writel(tmp, remapped_regs + mmGEN_INT_CNTL); | ||
1488 | |||
1489 | /* clear vline irq status */ | ||
1490 | writel(0x00000002, remapped_regs + mmGEN_INT_STATUS); | ||
1491 | } | ||
1492 | |||
1493 | |||
1494 | static void w100_InitExtMem(u32 mode) | ||
1495 | { | ||
1496 | switch(mode) { | ||
1497 | case LCD_SHARP_QVGA: | ||
1498 | /* QVGA doesn't use external memory | ||
1499 | nothing to do, really. */ | ||
1500 | break; | ||
1501 | case LCD_SHARP_VGA: | ||
1502 | writel(0x00007800, remapped_regs + mmMC_BIST_CTRL); | ||
1503 | writel(0x00040003, remapped_regs + mmMEM_EXT_CNTL); | ||
1504 | writel(0x00200021, remapped_regs + mmMEM_SDRAM_MODE_REG); | ||
1505 | udelay(100); | ||
1506 | writel(0x80200021, remapped_regs + mmMEM_SDRAM_MODE_REG); | ||
1507 | udelay(100); | ||
1508 | writel(0x00650021, remapped_regs + mmMEM_SDRAM_MODE_REG); | ||
1509 | udelay(100); | ||
1510 | writel(0x10002a4a, remapped_regs + mmMEM_EXT_TIMING_CNTL); | ||
1511 | writel(0x7ff87012, remapped_regs + mmMEM_IO_CNTL); | ||
1512 | break; | ||
1513 | default: | ||
1514 | break; | ||
1515 | } | ||
1516 | } | ||
1517 | |||
1518 | |||
1519 | #define RESCTL_ADRS 0x00 | ||
1520 | #define PHACTRL_ADRS 0x01 | ||
1521 | #define DUTYCTRL_ADRS 0x02 | ||
1522 | #define POWERREG0_ADRS 0x03 | ||
1523 | #define POWERREG1_ADRS 0x04 | ||
1524 | #define GPOR3_ADRS 0x05 | ||
1525 | #define PICTRL_ADRS 0x06 | ||
1526 | #define POLCTRL_ADRS 0x07 | ||
1527 | |||
1528 | #define RESCTL_QVGA 0x01 | ||
1529 | #define RESCTL_VGA 0x00 | ||
1530 | |||
1531 | #define POWER1_VW_ON 0x01 /* VW Supply FET ON */ | ||
1532 | #define POWER1_GVSS_ON 0x02 /* GVSS(-8V) Power Supply ON */ | ||
1533 | #define POWER1_VDD_ON 0x04 /* VDD(8V),SVSS(-4V) Power Supply ON */ | ||
1534 | |||
1535 | #define POWER1_VW_OFF 0x00 /* VW Supply FET OFF */ | ||
1536 | #define POWER1_GVSS_OFF 0x00 /* GVSS(-8V) Power Supply OFF */ | ||
1537 | #define POWER1_VDD_OFF 0x00 /* VDD(8V),SVSS(-4V) Power Supply OFF */ | ||
1538 | |||
1539 | #define POWER0_COM_DCLK 0x01 /* COM Voltage DC Bias DAC Serial Data Clock */ | ||
1540 | #define POWER0_COM_DOUT 0x02 /* COM Voltage DC Bias DAC Serial Data Out */ | ||
1541 | #define POWER0_DAC_ON 0x04 /* DAC Power Supply ON */ | ||
1542 | #define POWER0_COM_ON 0x08 /* COM Powewr Supply ON */ | ||
1543 | #define POWER0_VCC5_ON 0x10 /* VCC5 Power Supply ON */ | ||
1544 | |||
1545 | #define POWER0_DAC_OFF 0x00 /* DAC Power Supply OFF */ | ||
1546 | #define POWER0_COM_OFF 0x00 /* COM Powewr Supply OFF */ | ||
1547 | #define POWER0_VCC5_OFF 0x00 /* VCC5 Power Supply OFF */ | ||
1548 | |||
1549 | #define PICTRL_INIT_STATE 0x01 | ||
1550 | #define PICTRL_INIOFF 0x02 | ||
1551 | #define PICTRL_POWER_DOWN 0x04 | ||
1552 | #define PICTRL_COM_SIGNAL_OFF 0x08 | ||
1553 | #define PICTRL_DAC_SIGNAL_OFF 0x10 | ||
1554 | |||
1555 | #define PICTRL_POWER_ACTIVE (0) | ||
1556 | |||
1557 | #define POLCTRL_SYNC_POL_FALL 0x01 | ||
1558 | #define POLCTRL_EN_POL_FALL 0x02 | ||
1559 | #define POLCTRL_DATA_POL_FALL 0x04 | ||
1560 | #define POLCTRL_SYNC_ACT_H 0x08 | ||
1561 | #define POLCTRL_EN_ACT_L 0x10 | ||
1562 | |||
1563 | #define POLCTRL_SYNC_POL_RISE 0x00 | ||
1564 | #define POLCTRL_EN_POL_RISE 0x00 | ||
1565 | #define POLCTRL_DATA_POL_RISE 0x00 | ||
1566 | #define POLCTRL_SYNC_ACT_L 0x00 | ||
1567 | #define POLCTRL_EN_ACT_H 0x00 | ||
1568 | |||
1569 | #define PHACTRL_PHASE_MANUAL 0x01 | ||
1570 | |||
1571 | #define PHAD_QVGA_DEFAULT_VAL (9) | ||
1572 | #define COMADJ_DEFAULT (125) | ||
1573 | |||
1574 | static void lcdtg_ssp_send(u8 adrs, u8 data) | ||
1575 | { | ||
1576 | w100fb_ssp_send(adrs,data); | ||
1577 | } | ||
1578 | |||
1579 | /* | ||
1580 | * This is only a psuedo I2C interface. We can't use the standard kernel | ||
1581 | * routines as the interface is write only. We just assume the data is acked... | ||
1582 | */ | ||
1583 | static void lcdtg_ssp_i2c_send(u8 data) | ||
1584 | { | ||
1585 | lcdtg_ssp_send(POWERREG0_ADRS, data); | ||
1586 | udelay(10); | ||
1587 | } | ||
1588 | |||
1589 | static void lcdtg_i2c_send_bit(u8 data) | ||
1590 | { | ||
1591 | lcdtg_ssp_i2c_send(data); | ||
1592 | lcdtg_ssp_i2c_send(data | POWER0_COM_DCLK); | ||
1593 | lcdtg_ssp_i2c_send(data); | ||
1594 | } | ||
1595 | |||
1596 | static void lcdtg_i2c_send_start(u8 base) | ||
1597 | { | ||
1598 | lcdtg_ssp_i2c_send(base | POWER0_COM_DCLK | POWER0_COM_DOUT); | ||
1599 | lcdtg_ssp_i2c_send(base | POWER0_COM_DCLK); | ||
1600 | lcdtg_ssp_i2c_send(base); | ||
1601 | } | ||
1602 | |||
1603 | static void lcdtg_i2c_send_stop(u8 base) | ||
1604 | { | ||
1605 | lcdtg_ssp_i2c_send(base); | ||
1606 | lcdtg_ssp_i2c_send(base | POWER0_COM_DCLK); | ||
1607 | lcdtg_ssp_i2c_send(base | POWER0_COM_DCLK | POWER0_COM_DOUT); | ||
1608 | } | ||
1609 | |||
1610 | static void lcdtg_i2c_send_byte(u8 base, u8 data) | ||
1611 | { | ||
1612 | int i; | ||
1613 | for (i = 0; i < 8; i++) { | ||
1614 | if (data & 0x80) | ||
1615 | lcdtg_i2c_send_bit(base | POWER0_COM_DOUT); | ||
1616 | else | ||
1617 | lcdtg_i2c_send_bit(base); | ||
1618 | data <<= 1; | ||
1619 | } | ||
1620 | } | ||
1621 | |||
1622 | static void lcdtg_i2c_wait_ack(u8 base) | ||
1623 | { | ||
1624 | lcdtg_i2c_send_bit(base); | ||
1625 | } | ||
1626 | |||
1627 | static void lcdtg_set_common_voltage(u8 base_data, u8 data) | ||
1628 | { | ||
1629 | /* Set Common Voltage to M62332FP via I2C */ | ||
1630 | lcdtg_i2c_send_start(base_data); | ||
1631 | lcdtg_i2c_send_byte(base_data, 0x9c); | ||
1632 | lcdtg_i2c_wait_ack(base_data); | ||
1633 | lcdtg_i2c_send_byte(base_data, 0x00); | ||
1634 | lcdtg_i2c_wait_ack(base_data); | ||
1635 | lcdtg_i2c_send_byte(base_data, data); | ||
1636 | lcdtg_i2c_wait_ack(base_data); | ||
1637 | lcdtg_i2c_send_stop(base_data); | ||
1638 | } | ||
1639 | |||
1640 | static struct lcdtg_register_setting { | ||
1641 | u8 adrs; | ||
1642 | u8 data; | ||
1643 | u32 wait; | ||
1644 | } lcdtg_power_on_table[] = { | ||
1645 | |||
1646 | /* Initialize Internal Logic & Port */ | ||
1647 | { PICTRL_ADRS, | ||
1648 | PICTRL_POWER_DOWN | PICTRL_INIOFF | PICTRL_INIT_STATE | | ||
1649 | PICTRL_COM_SIGNAL_OFF | PICTRL_DAC_SIGNAL_OFF, | ||
1650 | 0 }, | ||
1651 | |||
1652 | { POWERREG0_ADRS, | ||
1653 | POWER0_COM_DCLK | POWER0_COM_DOUT | POWER0_DAC_OFF | POWER0_COM_OFF | | ||
1654 | POWER0_VCC5_OFF, | ||
1655 | 0 }, | ||
1656 | |||
1657 | { POWERREG1_ADRS, | ||
1658 | POWER1_VW_OFF | POWER1_GVSS_OFF | POWER1_VDD_OFF, | ||
1659 | 0 }, | ||
1660 | |||
1661 | /* VDD(+8V),SVSS(-4V) ON */ | ||
1662 | { POWERREG1_ADRS, | ||
1663 | POWER1_VW_OFF | POWER1_GVSS_OFF | POWER1_VDD_ON /* VDD ON */, | ||
1664 | 3000 }, | ||
1665 | |||
1666 | /* DAC ON */ | ||
1667 | { POWERREG0_ADRS, | ||
1668 | POWER0_COM_DCLK | POWER0_COM_DOUT | POWER0_DAC_ON /* DAC ON */ | | ||
1669 | POWER0_COM_OFF | POWER0_VCC5_OFF, | ||
1670 | 0 }, | ||
1671 | |||
1672 | /* INIB = H, INI = L */ | ||
1673 | { PICTRL_ADRS, | ||
1674 | /* PICTL[0] = H , PICTL[1] = PICTL[2] = PICTL[4] = L */ | ||
1675 | PICTRL_INIT_STATE | PICTRL_COM_SIGNAL_OFF, | ||
1676 | 0 }, | ||
1677 | |||
1678 | /* Set Common Voltage */ | ||
1679 | { 0xfe, 0, 0 }, | ||
1680 | |||
1681 | /* VCC5 ON */ | ||
1682 | { POWERREG0_ADRS, | ||
1683 | POWER0_COM_DCLK | POWER0_COM_DOUT | POWER0_DAC_ON /* DAC ON */ | | ||
1684 | POWER0_COM_OFF | POWER0_VCC5_ON /* VCC5 ON */, | ||
1685 | 0 }, | ||
1686 | |||
1687 | /* GVSS(-8V) ON */ | ||
1688 | { POWERREG1_ADRS, | ||
1689 | POWER1_VW_OFF | POWER1_GVSS_ON /* GVSS ON */ | | ||
1690 | POWER1_VDD_ON /* VDD ON */, | ||
1691 | 2000 }, | ||
1692 | |||
1693 | /* COM SIGNAL ON (PICTL[3] = L) */ | ||
1694 | { PICTRL_ADRS, | ||
1695 | PICTRL_INIT_STATE, | ||
1696 | 0 }, | ||
1697 | |||
1698 | /* COM ON */ | ||
1699 | { POWERREG0_ADRS, | ||
1700 | POWER0_COM_DCLK | POWER0_COM_DOUT | POWER0_DAC_ON /* DAC ON */ | | ||
1701 | POWER0_COM_ON /* COM ON */ | POWER0_VCC5_ON /* VCC5_ON */, | ||
1702 | 0 }, | ||
1703 | |||
1704 | /* VW ON */ | ||
1705 | { POWERREG1_ADRS, | ||
1706 | POWER1_VW_ON /* VW ON */ | POWER1_GVSS_ON /* GVSS ON */ | | ||
1707 | POWER1_VDD_ON /* VDD ON */, | ||
1708 | 0 /* Wait 100ms */ }, | ||
1709 | |||
1710 | /* Signals output enable */ | ||
1711 | { PICTRL_ADRS, | ||
1712 | 0 /* Signals output enable */, | ||
1713 | 0 }, | ||
1714 | |||
1715 | { PHACTRL_ADRS, | ||
1716 | PHACTRL_PHASE_MANUAL, | ||
1717 | 0 }, | ||
1718 | |||
1719 | /* Initialize for Input Signals from ATI */ | ||
1720 | { POLCTRL_ADRS, | ||
1721 | POLCTRL_SYNC_POL_RISE | POLCTRL_EN_POL_RISE | POLCTRL_DATA_POL_RISE | | ||
1722 | POLCTRL_SYNC_ACT_L | POLCTRL_EN_ACT_H, | ||
1723 | 1000 /*100000*/ /* Wait 100ms */ }, | ||
1724 | |||
1725 | /* end mark */ | ||
1726 | { 0xff, 0, 0 } | ||
1727 | }; | ||
1728 | |||
1729 | static void lcdtg_resume(void) | ||
1730 | { | ||
1731 | if (current_par->lcdMode == LCD_MODE_480 || current_par->lcdMode == LCD_MODE_640) { | ||
1732 | lcdtg_hw_init(LCD_SHARP_VGA); | ||
1733 | } else { | ||
1734 | lcdtg_hw_init(LCD_SHARP_QVGA); | ||
1735 | } | ||
1736 | } | ||
1737 | |||
1738 | static void lcdtg_suspend(void) | ||
1739 | { | ||
1740 | int i; | ||
1741 | |||
1742 | for (i = 0; i < (current_par->xres * current_par->yres); i++) { | ||
1743 | writew(0xffff, remapped_fbuf + (2*i)); | ||
1744 | } | ||
1745 | |||
1746 | /* 60Hz x 2 frame = 16.7msec x 2 = 33.4 msec */ | ||
1747 | mdelay(34); | ||
1748 | |||
1749 | /* (1)VW OFF */ | ||
1750 | lcdtg_ssp_send(POWERREG1_ADRS, POWER1_VW_OFF | POWER1_GVSS_ON | POWER1_VDD_ON); | ||
1751 | |||
1752 | /* (2)COM OFF */ | ||
1753 | lcdtg_ssp_send(PICTRL_ADRS, PICTRL_COM_SIGNAL_OFF); | ||
1754 | lcdtg_ssp_send(POWERREG0_ADRS, POWER0_DAC_ON | POWER0_COM_OFF | POWER0_VCC5_ON); | ||
1755 | |||
1756 | /* (3)Set Common Voltage Bias 0V */ | ||
1757 | lcdtg_set_common_voltage(POWER0_DAC_ON | POWER0_COM_OFF | POWER0_VCC5_ON, 0); | ||
1758 | |||
1759 | /* (4)GVSS OFF */ | ||
1760 | lcdtg_ssp_send(POWERREG1_ADRS, POWER1_VW_OFF | POWER1_GVSS_OFF | POWER1_VDD_ON); | ||
1761 | |||
1762 | /* (5)VCC5 OFF */ | ||
1763 | lcdtg_ssp_send(POWERREG0_ADRS, POWER0_DAC_ON | POWER0_COM_OFF | POWER0_VCC5_OFF); | ||
1764 | |||
1765 | /* (6)Set PDWN, INIOFF, DACOFF */ | ||
1766 | lcdtg_ssp_send(PICTRL_ADRS, PICTRL_INIOFF | PICTRL_DAC_SIGNAL_OFF | | ||
1767 | PICTRL_POWER_DOWN | PICTRL_COM_SIGNAL_OFF); | ||
1768 | |||
1769 | /* (7)DAC OFF */ | ||
1770 | lcdtg_ssp_send(POWERREG0_ADRS, POWER0_DAC_OFF | POWER0_COM_OFF | POWER0_VCC5_OFF); | ||
1771 | |||
1772 | /* (8)VDD OFF */ | ||
1773 | lcdtg_ssp_send(POWERREG1_ADRS, POWER1_VW_OFF | POWER1_GVSS_OFF | POWER1_VDD_OFF); | ||
1774 | |||
1775 | } | ||
1776 | |||
1777 | static void lcdtg_set_phadadj(u32 mode) | ||
1778 | { | ||
1779 | int adj; | ||
1780 | |||
1781 | if (mode == LCD_SHARP_VGA) { | ||
1782 | /* Setting for VGA */ | ||
1783 | adj = current_par->phadadj; | ||
1784 | if (adj < 0) { | ||
1785 | adj = PHACTRL_PHASE_MANUAL; | ||
1786 | } else { | ||
1787 | adj = ((adj & 0x0f) << 1) | PHACTRL_PHASE_MANUAL; | ||
1788 | } | ||
1789 | } else { | ||
1790 | /* Setting for QVGA */ | ||
1791 | adj = (PHAD_QVGA_DEFAULT_VAL << 1) | PHACTRL_PHASE_MANUAL; | ||
1792 | } | ||
1793 | lcdtg_ssp_send(PHACTRL_ADRS, adj); | ||
1794 | } | ||
1795 | |||
1796 | static void lcdtg_hw_init(u32 mode) | ||
1797 | { | ||
1798 | int i; | ||
1799 | int comadj; | ||
1800 | |||
1801 | i = 0; | ||
1802 | while(lcdtg_power_on_table[i].adrs != 0xff) { | ||
1803 | if (lcdtg_power_on_table[i].adrs == 0xfe) { | ||
1804 | /* Set Common Voltage */ | ||
1805 | comadj = current_par->comadj; | ||
1806 | if (comadj < 0) { | ||
1807 | comadj = COMADJ_DEFAULT; | ||
1808 | } | ||
1809 | lcdtg_set_common_voltage((POWER0_DAC_ON | POWER0_COM_OFF | POWER0_VCC5_OFF), comadj); | ||
1810 | } else if (lcdtg_power_on_table[i].adrs == PHACTRL_ADRS) { | ||
1811 | /* Set Phase Adjuct */ | ||
1812 | lcdtg_set_phadadj(mode); | ||
1813 | } else { | ||
1814 | /* Other */ | ||
1815 | lcdtg_ssp_send(lcdtg_power_on_table[i].adrs, lcdtg_power_on_table[i].data); | ||
1816 | } | ||
1817 | if (lcdtg_power_on_table[i].wait != 0) | ||
1818 | udelay(lcdtg_power_on_table[i].wait); | ||
1819 | i++; | ||
1820 | } | ||
1821 | |||
1822 | switch(mode) { | ||
1823 | case LCD_SHARP_QVGA: | ||
1824 | /* Set Lcd Resolution (QVGA) */ | ||
1825 | lcdtg_ssp_send(RESCTL_ADRS, RESCTL_QVGA); | ||
1826 | break; | ||
1827 | case LCD_SHARP_VGA: | ||
1828 | /* Set Lcd Resolution (VGA) */ | ||
1829 | lcdtg_ssp_send(RESCTL_ADRS, RESCTL_VGA); | ||
1830 | break; | ||
1831 | default: | ||
1832 | break; | ||
1833 | } | ||
1834 | } | ||
1835 | |||
1836 | static void lcdtg_lcd_change(u32 mode) | ||
1837 | { | ||
1838 | /* Set Phase Adjuct */ | ||
1839 | lcdtg_set_phadadj(mode); | ||
1840 | |||
1841 | if (mode == LCD_SHARP_VGA) | ||
1842 | /* Set Lcd Resolution (VGA) */ | ||
1843 | lcdtg_ssp_send(RESCTL_ADRS, RESCTL_VGA); | ||
1844 | else if (mode == LCD_SHARP_QVGA) | ||
1845 | /* Set Lcd Resolution (QVGA) */ | ||
1846 | lcdtg_ssp_send(RESCTL_ADRS, RESCTL_QVGA); | ||
1847 | } | ||
1848 | |||
1849 | |||
1850 | static struct device_driver w100fb_driver = { | ||
1851 | .name = "w100fb", | ||
1852 | .bus = &platform_bus_type, | ||
1853 | .probe = w100fb_probe, | ||
1854 | .remove = w100fb_remove, | ||
1855 | .suspend = w100fb_suspend, | ||
1856 | .resume = w100fb_resume, | ||
1857 | }; | ||
1858 | |||
1859 | int __devinit w100fb_init(void) | ||
1860 | { | ||
1861 | return driver_register(&w100fb_driver); | ||
1862 | } | ||
1863 | |||
1864 | void __exit w100fb_cleanup(void) | ||
1865 | { | ||
1866 | driver_unregister(&w100fb_driver); | ||
1867 | } | ||
1868 | |||
1869 | module_init(w100fb_init); | ||
1870 | module_exit(w100fb_cleanup); | ||
1871 | |||
1872 | MODULE_DESCRIPTION("ATI Imageon w100 framebuffer driver"); | ||
1873 | MODULE_LICENSE("GPLv2"); | ||