Commit | Line | Data |
---|---|---|
1da177e4 LT |
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 | ||
060b8845 | 104 | static ssize_t rotation_show(struct device *dev, struct device_attribute *attr, char *buf) |
1da177e4 LT |
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 | ||
060b8845 | 112 | static ssize_t rotation_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) |
1da177e4 LT |
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 | ||
060b8845 | 137 | static ssize_t w100fb_reg_read(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) |
1da177e4 LT |
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 | ||
060b8845 | 149 | static ssize_t w100fb_reg_write(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) |
1da177e4 LT |
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 | ||
060b8845 | 166 | static ssize_t fastsysclk_show(struct device *dev, struct device_attribute *attr, char *buf) |
1da177e4 LT |
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 | ||
060b8845 | 174 | static ssize_t fastsysclk_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) |
1da177e4 LT |
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 | |
9bfd354b | 547 | static int w100fb_suspend(struct device *dev, pm_message_t state, u32 level) |
1da177e4 LT |
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"); |