Merge branch 'merge' of git://git.kernel.org/pub/scm/linux/kernel/git/paulus/powerpc
[deliverable/linux.git] / drivers / video / w100fb.c
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-2006 Richard Purdie
8 * Copyright (c) 2005 Ian Molton
9 * Copyright (c) 2006 Alberto Mardegan
10 *
11 * Rewritten for 2.6 by Richard Purdie <rpurdie@rpsys.net>
12 *
13 * Generic platform support by Ian Molton <spyro@f2s.com>
14 * and Richard Purdie <rpurdie@rpsys.net>
15 *
16 * w32xx support by Ian Molton
17 *
18 * Hardware acceleration support by Alberto Mardegan
19 * <mardy@users.sourceforge.net>
20 *
21 * This program is free software; you can redistribute it and/or modify
22 * it under the terms of the GNU General Public License version 2 as
23 * published by the Free Software Foundation.
24 *
25 */
26
27 #include <linux/delay.h>
28 #include <linux/fb.h>
29 #include <linux/init.h>
30 #include <linux/kernel.h>
31 #include <linux/mm.h>
32 #include <linux/platform_device.h>
33 #include <linux/string.h>
34 #include <linux/vmalloc.h>
35 #include <asm/io.h>
36 #include <asm/uaccess.h>
37 #include <video/w100fb.h>
38 #include "w100fb.h"
39
40 /*
41 * Prototypes
42 */
43 static void w100_suspend(u32 mode);
44 static void w100_vsync(void);
45 static void w100_hw_init(struct w100fb_par*);
46 static void w100_pwm_setup(struct w100fb_par*);
47 static void w100_init_clocks(struct w100fb_par*);
48 static void w100_setup_memory(struct w100fb_par*);
49 static void w100_init_lcd(struct w100fb_par*);
50 static void w100_set_dispregs(struct w100fb_par*);
51 static void w100_update_enable(void);
52 static void w100_update_disable(void);
53 static void calc_hsync(struct w100fb_par *par);
54 static void w100_init_graphic_engine(struct w100fb_par *par);
55 struct w100_pll_info *w100_get_xtal_table(unsigned int freq);
56
57 /* Pseudo palette size */
58 #define MAX_PALETTES 16
59
60 #define W100_SUSPEND_EXTMEM 0
61 #define W100_SUSPEND_ALL 1
62
63 #define BITS_PER_PIXEL 16
64
65 /* Remapped addresses for base cfg, memmapped regs and the frame buffer itself */
66 static void *remapped_base;
67 static void *remapped_regs;
68 static void *remapped_fbuf;
69
70 #define REMAPPED_FB_LEN 0x15ffff
71
72 /* This is the offset in the w100's address space we map the current
73 framebuffer memory to. We use the position of external memory as
74 we can remap internal memory to there if external isn't present. */
75 #define W100_FB_BASE MEM_EXT_BASE_VALUE
76
77
78 /*
79 * Sysfs functions
80 */
81 static ssize_t flip_show(struct device *dev, struct device_attribute *attr, char *buf)
82 {
83 struct fb_info *info = dev_get_drvdata(dev);
84 struct w100fb_par *par=info->par;
85
86 return sprintf(buf, "%d\n",par->flip);
87 }
88
89 static ssize_t flip_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
90 {
91 unsigned int flip;
92 struct fb_info *info = dev_get_drvdata(dev);
93 struct w100fb_par *par=info->par;
94
95 flip = simple_strtoul(buf, NULL, 10);
96
97 if (flip > 0)
98 par->flip = 1;
99 else
100 par->flip = 0;
101
102 w100_update_disable();
103 w100_set_dispregs(par);
104 w100_update_enable();
105
106 calc_hsync(par);
107
108 return count;
109 }
110
111 static DEVICE_ATTR(flip, 0644, flip_show, flip_store);
112
113 static ssize_t w100fb_reg_read(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
114 {
115 unsigned long regs, param;
116 regs = simple_strtoul(buf, NULL, 16);
117 param = readl(remapped_regs + regs);
118 printk("Read Register 0x%08lX: 0x%08lX\n", regs, param);
119 return count;
120 }
121
122 static DEVICE_ATTR(reg_read, 0200, NULL, w100fb_reg_read);
123
124 static ssize_t w100fb_reg_write(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
125 {
126 unsigned long regs, param;
127 sscanf(buf, "%lx %lx", &regs, &param);
128
129 if (regs <= 0x2000) {
130 printk("Write Register 0x%08lX: 0x%08lX\n", regs, param);
131 writel(param, remapped_regs + regs);
132 }
133
134 return count;
135 }
136
137 static DEVICE_ATTR(reg_write, 0200, NULL, w100fb_reg_write);
138
139
140 static ssize_t fastpllclk_show(struct device *dev, struct device_attribute *attr, char *buf)
141 {
142 struct fb_info *info = dev_get_drvdata(dev);
143 struct w100fb_par *par=info->par;
144
145 return sprintf(buf, "%d\n",par->fastpll_mode);
146 }
147
148 static ssize_t fastpllclk_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
149 {
150 struct fb_info *info = dev_get_drvdata(dev);
151 struct w100fb_par *par=info->par;
152
153 if (simple_strtoul(buf, NULL, 10) > 0) {
154 par->fastpll_mode=1;
155 printk("w100fb: Using fast system clock (if possible)\n");
156 } else {
157 par->fastpll_mode=0;
158 printk("w100fb: Using normal system clock\n");
159 }
160
161 w100_init_clocks(par);
162 calc_hsync(par);
163
164 return count;
165 }
166
167 static DEVICE_ATTR(fastpllclk, 0644, fastpllclk_show, fastpllclk_store);
168
169 /*
170 * Some touchscreens need hsync information from the video driver to
171 * function correctly. We export it here.
172 */
173 unsigned long w100fb_get_hsynclen(struct device *dev)
174 {
175 struct fb_info *info = dev_get_drvdata(dev);
176 struct w100fb_par *par=info->par;
177
178 /* If display is blanked/suspended, hsync isn't active */
179 if (par->blanked)
180 return 0;
181 else
182 return par->hsync_len;
183 }
184 EXPORT_SYMBOL(w100fb_get_hsynclen);
185
186 static void w100fb_clear_screen(struct w100fb_par *par)
187 {
188 memset_io(remapped_fbuf + (W100_FB_BASE-MEM_WINDOW_BASE), 0, (par->xres * par->yres * BITS_PER_PIXEL/8));
189 }
190
191
192 /*
193 * Set a palette value from rgb components
194 */
195 static int w100fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
196 u_int trans, struct fb_info *info)
197 {
198 unsigned int val;
199 int ret = 1;
200
201 /*
202 * If greyscale is true, then we convert the RGB value
203 * to greyscale no matter what visual we are using.
204 */
205 if (info->var.grayscale)
206 red = green = blue = (19595 * red + 38470 * green + 7471 * blue) >> 16;
207
208 /*
209 * 16-bit True Colour. We encode the RGB value
210 * according to the RGB bitfield information.
211 */
212 if (regno < MAX_PALETTES) {
213 u32 *pal = info->pseudo_palette;
214
215 val = (red & 0xf800) | ((green & 0xfc00) >> 5) | ((blue & 0xf800) >> 11);
216 pal[regno] = val;
217 ret = 0;
218 }
219 return ret;
220 }
221
222
223 /*
224 * Blank the display based on value in blank_mode
225 */
226 static int w100fb_blank(int blank_mode, struct fb_info *info)
227 {
228 struct w100fb_par *par = info->par;
229 struct w100_tg_info *tg = par->mach->tg;
230
231 switch(blank_mode) {
232
233 case FB_BLANK_NORMAL: /* Normal blanking */
234 case FB_BLANK_VSYNC_SUSPEND: /* VESA blank (vsync off) */
235 case FB_BLANK_HSYNC_SUSPEND: /* VESA blank (hsync off) */
236 case FB_BLANK_POWERDOWN: /* Poweroff */
237 if (par->blanked == 0) {
238 if(tg && tg->suspend)
239 tg->suspend(par);
240 par->blanked = 1;
241 }
242 break;
243
244 case FB_BLANK_UNBLANK: /* Unblanking */
245 if (par->blanked != 0) {
246 if(tg && tg->resume)
247 tg->resume(par);
248 par->blanked = 0;
249 }
250 break;
251 }
252 return 0;
253 }
254
255
256 static void w100_fifo_wait(int entries)
257 {
258 union rbbm_status_u status;
259 int i;
260
261 for (i = 0; i < 2000000; i++) {
262 status.val = readl(remapped_regs + mmRBBM_STATUS);
263 if (status.f.cmdfifo_avail >= entries)
264 return;
265 udelay(1);
266 }
267 printk(KERN_ERR "w100fb: FIFO Timeout!\n");
268 }
269
270
271 static int w100fb_sync(struct fb_info *info)
272 {
273 union rbbm_status_u status;
274 int i;
275
276 for (i = 0; i < 2000000; i++) {
277 status.val = readl(remapped_regs + mmRBBM_STATUS);
278 if (!status.f.gui_active)
279 return 0;
280 udelay(1);
281 }
282 printk(KERN_ERR "w100fb: Graphic engine timeout!\n");
283 return -EBUSY;
284 }
285
286
287 static void w100_init_graphic_engine(struct w100fb_par *par)
288 {
289 union dp_gui_master_cntl_u gmc;
290 union dp_mix_u dp_mix;
291 union dp_datatype_u dp_datatype;
292 union dp_cntl_u dp_cntl;
293
294 w100_fifo_wait(4);
295 writel(W100_FB_BASE, remapped_regs + mmDST_OFFSET);
296 writel(par->xres, remapped_regs + mmDST_PITCH);
297 writel(W100_FB_BASE, remapped_regs + mmSRC_OFFSET);
298 writel(par->xres, remapped_regs + mmSRC_PITCH);
299
300 w100_fifo_wait(3);
301 writel(0, remapped_regs + mmSC_TOP_LEFT);
302 writel((par->yres << 16) | par->xres, remapped_regs + mmSC_BOTTOM_RIGHT);
303 writel(0x1fff1fff, remapped_regs + mmSRC_SC_BOTTOM_RIGHT);
304
305 w100_fifo_wait(4);
306 dp_cntl.val = 0;
307 dp_cntl.f.dst_x_dir = 1;
308 dp_cntl.f.dst_y_dir = 1;
309 dp_cntl.f.src_x_dir = 1;
310 dp_cntl.f.src_y_dir = 1;
311 dp_cntl.f.dst_major_x = 1;
312 dp_cntl.f.src_major_x = 1;
313 writel(dp_cntl.val, remapped_regs + mmDP_CNTL);
314
315 gmc.val = 0;
316 gmc.f.gmc_src_pitch_offset_cntl = 1;
317 gmc.f.gmc_dst_pitch_offset_cntl = 1;
318 gmc.f.gmc_src_clipping = 1;
319 gmc.f.gmc_dst_clipping = 1;
320 gmc.f.gmc_brush_datatype = GMC_BRUSH_NONE;
321 gmc.f.gmc_dst_datatype = 3; /* from DstType_16Bpp_444 */
322 gmc.f.gmc_src_datatype = SRC_DATATYPE_EQU_DST;
323 gmc.f.gmc_byte_pix_order = 1;
324 gmc.f.gmc_default_sel = 0;
325 gmc.f.gmc_rop3 = ROP3_SRCCOPY;
326 gmc.f.gmc_dp_src_source = DP_SRC_MEM_RECTANGULAR;
327 gmc.f.gmc_clr_cmp_fcn_dis = 1;
328 gmc.f.gmc_wr_msk_dis = 1;
329 gmc.f.gmc_dp_op = DP_OP_ROP;
330 writel(gmc.val, remapped_regs + mmDP_GUI_MASTER_CNTL);
331
332 dp_datatype.val = dp_mix.val = 0;
333 dp_datatype.f.dp_dst_datatype = gmc.f.gmc_dst_datatype;
334 dp_datatype.f.dp_brush_datatype = gmc.f.gmc_brush_datatype;
335 dp_datatype.f.dp_src2_type = 0;
336 dp_datatype.f.dp_src2_datatype = gmc.f.gmc_src_datatype;
337 dp_datatype.f.dp_src_datatype = gmc.f.gmc_src_datatype;
338 dp_datatype.f.dp_byte_pix_order = gmc.f.gmc_byte_pix_order;
339 writel(dp_datatype.val, remapped_regs + mmDP_DATATYPE);
340
341 dp_mix.f.dp_src_source = gmc.f.gmc_dp_src_source;
342 dp_mix.f.dp_src2_source = 1;
343 dp_mix.f.dp_rop3 = gmc.f.gmc_rop3;
344 dp_mix.f.dp_op = gmc.f.gmc_dp_op;
345 writel(dp_mix.val, remapped_regs + mmDP_MIX);
346 }
347
348
349 static void w100fb_fillrect(struct fb_info *info,
350 const struct fb_fillrect *rect)
351 {
352 union dp_gui_master_cntl_u gmc;
353
354 if (info->state != FBINFO_STATE_RUNNING)
355 return;
356 if (info->flags & FBINFO_HWACCEL_DISABLED) {
357 cfb_fillrect(info, rect);
358 return;
359 }
360
361 gmc.val = readl(remapped_regs + mmDP_GUI_MASTER_CNTL);
362 gmc.f.gmc_rop3 = ROP3_PATCOPY;
363 gmc.f.gmc_brush_datatype = GMC_BRUSH_SOLID_COLOR;
364 w100_fifo_wait(2);
365 writel(gmc.val, remapped_regs + mmDP_GUI_MASTER_CNTL);
366 writel(rect->color, remapped_regs + mmDP_BRUSH_FRGD_CLR);
367
368 w100_fifo_wait(2);
369 writel((rect->dy << 16) | (rect->dx & 0xffff), remapped_regs + mmDST_Y_X);
370 writel((rect->width << 16) | (rect->height & 0xffff),
371 remapped_regs + mmDST_WIDTH_HEIGHT);
372 }
373
374
375 static void w100fb_copyarea(struct fb_info *info,
376 const struct fb_copyarea *area)
377 {
378 u32 dx = area->dx, dy = area->dy, sx = area->sx, sy = area->sy;
379 u32 h = area->height, w = area->width;
380 union dp_gui_master_cntl_u gmc;
381
382 if (info->state != FBINFO_STATE_RUNNING)
383 return;
384 if (info->flags & FBINFO_HWACCEL_DISABLED) {
385 cfb_copyarea(info, area);
386 return;
387 }
388
389 gmc.val = readl(remapped_regs + mmDP_GUI_MASTER_CNTL);
390 gmc.f.gmc_rop3 = ROP3_SRCCOPY;
391 gmc.f.gmc_brush_datatype = GMC_BRUSH_NONE;
392 w100_fifo_wait(1);
393 writel(gmc.val, remapped_regs + mmDP_GUI_MASTER_CNTL);
394
395 w100_fifo_wait(3);
396 writel((sy << 16) | (sx & 0xffff), remapped_regs + mmSRC_Y_X);
397 writel((dy << 16) | (dx & 0xffff), remapped_regs + mmDST_Y_X);
398 writel((w << 16) | (h & 0xffff), remapped_regs + mmDST_WIDTH_HEIGHT);
399 }
400
401
402 /*
403 * Change the resolution by calling the appropriate hardware functions
404 */
405 static void w100fb_activate_var(struct w100fb_par *par)
406 {
407 struct w100_tg_info *tg = par->mach->tg;
408
409 w100_pwm_setup(par);
410 w100_setup_memory(par);
411 w100_init_clocks(par);
412 w100fb_clear_screen(par);
413 w100_vsync();
414
415 w100_update_disable();
416 w100_init_lcd(par);
417 w100_set_dispregs(par);
418 w100_update_enable();
419 w100_init_graphic_engine(par);
420
421 calc_hsync(par);
422
423 if (!par->blanked && tg && tg->change)
424 tg->change(par);
425 }
426
427
428 /* Select the smallest mode that allows the desired resolution to be
429 * displayed. If desired, the x and y parameters can be rounded up to
430 * match the selected mode.
431 */
432 static struct w100_mode *w100fb_get_mode(struct w100fb_par *par, unsigned int *x, unsigned int *y, int saveval)
433 {
434 struct w100_mode *mode = NULL;
435 struct w100_mode *modelist = par->mach->modelist;
436 unsigned int best_x = 0xffffffff, best_y = 0xffffffff;
437 unsigned int i;
438
439 for (i = 0 ; i < par->mach->num_modes ; i++) {
440 if (modelist[i].xres >= *x && modelist[i].yres >= *y &&
441 modelist[i].xres < best_x && modelist[i].yres < best_y) {
442 best_x = modelist[i].xres;
443 best_y = modelist[i].yres;
444 mode = &modelist[i];
445 } else if(modelist[i].xres >= *y && modelist[i].yres >= *x &&
446 modelist[i].xres < best_y && modelist[i].yres < best_x) {
447 best_x = modelist[i].yres;
448 best_y = modelist[i].xres;
449 mode = &modelist[i];
450 }
451 }
452
453 if (mode && saveval) {
454 *x = best_x;
455 *y = best_y;
456 }
457
458 return mode;
459 }
460
461
462 /*
463 * w100fb_check_var():
464 * Get the video params out of 'var'. If a value doesn't fit, round it up,
465 * if it's too big, return -EINVAL.
466 */
467 static int w100fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
468 {
469 struct w100fb_par *par=info->par;
470
471 if(!w100fb_get_mode(par, &var->xres, &var->yres, 1))
472 return -EINVAL;
473
474 if (par->mach->mem && ((var->xres*var->yres*BITS_PER_PIXEL/8) > (par->mach->mem->size+1)))
475 return -EINVAL;
476
477 if (!par->mach->mem && ((var->xres*var->yres*BITS_PER_PIXEL/8) > (MEM_INT_SIZE+1)))
478 return -EINVAL;
479
480 var->xres_virtual = max(var->xres_virtual, var->xres);
481 var->yres_virtual = max(var->yres_virtual, var->yres);
482
483 if (var->bits_per_pixel > BITS_PER_PIXEL)
484 return -EINVAL;
485 else
486 var->bits_per_pixel = BITS_PER_PIXEL;
487
488 var->red.offset = 11;
489 var->red.length = 5;
490 var->green.offset = 5;
491 var->green.length = 6;
492 var->blue.offset = 0;
493 var->blue.length = 5;
494 var->transp.offset = var->transp.length = 0;
495
496 var->nonstd = 0;
497 var->height = -1;
498 var->width = -1;
499 var->vmode = FB_VMODE_NONINTERLACED;
500 var->sync = 0;
501 var->pixclock = 0x04; /* 171521; */
502
503 return 0;
504 }
505
506
507 /*
508 * w100fb_set_par():
509 * Set the user defined part of the display for the specified console
510 * by looking at the values in info.var
511 */
512 static int w100fb_set_par(struct fb_info *info)
513 {
514 struct w100fb_par *par=info->par;
515
516 if (par->xres != info->var.xres || par->yres != info->var.yres) {
517 par->xres = info->var.xres;
518 par->yres = info->var.yres;
519 par->mode = w100fb_get_mode(par, &par->xres, &par->yres, 0);
520
521 info->fix.visual = FB_VISUAL_TRUECOLOR;
522 info->fix.ypanstep = 0;
523 info->fix.ywrapstep = 0;
524 info->fix.line_length = par->xres * BITS_PER_PIXEL / 8;
525
526 if ((par->xres*par->yres*BITS_PER_PIXEL/8) > (MEM_INT_SIZE+1)) {
527 par->extmem_active = 1;
528 info->fix.smem_len = par->mach->mem->size+1;
529 } else {
530 par->extmem_active = 0;
531 info->fix.smem_len = MEM_INT_SIZE+1;
532 }
533
534 w100fb_activate_var(par);
535 }
536 return 0;
537 }
538
539
540 /*
541 * Frame buffer operations
542 */
543 static struct fb_ops w100fb_ops = {
544 .owner = THIS_MODULE,
545 .fb_check_var = w100fb_check_var,
546 .fb_set_par = w100fb_set_par,
547 .fb_setcolreg = w100fb_setcolreg,
548 .fb_blank = w100fb_blank,
549 .fb_fillrect = w100fb_fillrect,
550 .fb_copyarea = w100fb_copyarea,
551 .fb_imageblit = cfb_imageblit,
552 .fb_sync = w100fb_sync,
553 };
554
555 #ifdef CONFIG_PM
556 static void w100fb_save_vidmem(struct w100fb_par *par)
557 {
558 int memsize;
559
560 if (par->extmem_active) {
561 memsize=par->mach->mem->size;
562 par->saved_extmem = vmalloc(memsize);
563 if (par->saved_extmem)
564 memcpy_fromio(par->saved_extmem, remapped_fbuf + (W100_FB_BASE-MEM_WINDOW_BASE), memsize);
565 }
566 memsize=MEM_INT_SIZE;
567 par->saved_intmem = vmalloc(memsize);
568 if (par->saved_intmem && par->extmem_active)
569 memcpy_fromio(par->saved_intmem, remapped_fbuf + (W100_FB_BASE-MEM_INT_BASE_VALUE), memsize);
570 else if (par->saved_intmem)
571 memcpy_fromio(par->saved_intmem, remapped_fbuf + (W100_FB_BASE-MEM_WINDOW_BASE), memsize);
572 }
573
574 static void w100fb_restore_vidmem(struct w100fb_par *par)
575 {
576 int memsize;
577
578 if (par->extmem_active && par->saved_extmem) {
579 memsize=par->mach->mem->size;
580 memcpy_toio(remapped_fbuf + (W100_FB_BASE-MEM_WINDOW_BASE), par->saved_extmem, memsize);
581 vfree(par->saved_extmem);
582 }
583 if (par->saved_intmem) {
584 memsize=MEM_INT_SIZE;
585 if (par->extmem_active)
586 memcpy_toio(remapped_fbuf + (W100_FB_BASE-MEM_INT_BASE_VALUE), par->saved_intmem, memsize);
587 else
588 memcpy_toio(remapped_fbuf + (W100_FB_BASE-MEM_WINDOW_BASE), par->saved_intmem, memsize);
589 vfree(par->saved_intmem);
590 }
591 }
592
593 static int w100fb_suspend(struct platform_device *dev, pm_message_t state)
594 {
595 struct fb_info *info = platform_get_drvdata(dev);
596 struct w100fb_par *par=info->par;
597 struct w100_tg_info *tg = par->mach->tg;
598
599 w100fb_save_vidmem(par);
600 if(tg && tg->suspend)
601 tg->suspend(par);
602 w100_suspend(W100_SUSPEND_ALL);
603 par->blanked = 1;
604
605 return 0;
606 }
607
608 static int w100fb_resume(struct platform_device *dev)
609 {
610 struct fb_info *info = platform_get_drvdata(dev);
611 struct w100fb_par *par=info->par;
612 struct w100_tg_info *tg = par->mach->tg;
613
614 w100_hw_init(par);
615 w100fb_activate_var(par);
616 w100fb_restore_vidmem(par);
617 if(tg && tg->resume)
618 tg->resume(par);
619 par->blanked = 0;
620
621 return 0;
622 }
623 #else
624 #define w100fb_suspend NULL
625 #define w100fb_resume NULL
626 #endif
627
628
629 int __init w100fb_probe(struct platform_device *pdev)
630 {
631 int err = -EIO;
632 struct w100fb_mach_info *inf;
633 struct fb_info *info = NULL;
634 struct w100fb_par *par;
635 struct resource *mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
636 unsigned int chip_id;
637
638 if (!mem)
639 return -EINVAL;
640
641 /* Remap the chip base address */
642 remapped_base = ioremap_nocache(mem->start+W100_CFG_BASE, W100_CFG_LEN);
643 if (remapped_base == NULL)
644 goto out;
645
646 /* Map the register space */
647 remapped_regs = ioremap_nocache(mem->start+W100_REG_BASE, W100_REG_LEN);
648 if (remapped_regs == NULL)
649 goto out;
650
651 /* Identify the chip */
652 printk("Found ");
653 chip_id = readl(remapped_regs + mmCHIP_ID);
654 switch(chip_id) {
655 case CHIP_ID_W100: printk("w100"); break;
656 case CHIP_ID_W3200: printk("w3200"); break;
657 case CHIP_ID_W3220: printk("w3220"); break;
658 default:
659 printk("Unknown imageon chip ID\n");
660 err = -ENODEV;
661 goto out;
662 }
663 printk(" at 0x%08lx.\n", (unsigned long) mem->start+W100_CFG_BASE);
664
665 /* Remap the framebuffer */
666 remapped_fbuf = ioremap_nocache(mem->start+MEM_WINDOW_BASE, MEM_WINDOW_SIZE);
667 if (remapped_fbuf == NULL)
668 goto out;
669
670 info=framebuffer_alloc(sizeof(struct w100fb_par), &pdev->dev);
671 if (!info) {
672 err = -ENOMEM;
673 goto out;
674 }
675
676 par = info->par;
677 platform_set_drvdata(pdev, info);
678
679 inf = pdev->dev.platform_data;
680 par->chip_id = chip_id;
681 par->mach = inf;
682 par->fastpll_mode = 0;
683 par->blanked = 0;
684
685 par->pll_table=w100_get_xtal_table(inf->xtal_freq);
686 if (!par->pll_table) {
687 printk(KERN_ERR "No matching Xtal definition found\n");
688 err = -EINVAL;
689 goto out;
690 }
691
692 info->pseudo_palette = kmalloc(sizeof (u32) * MAX_PALETTES, GFP_KERNEL);
693 if (!info->pseudo_palette) {
694 err = -ENOMEM;
695 goto out;
696 }
697
698 info->fbops = &w100fb_ops;
699 info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_COPYAREA |
700 FBINFO_HWACCEL_FILLRECT;
701 info->node = -1;
702 info->screen_base = remapped_fbuf + (W100_FB_BASE-MEM_WINDOW_BASE);
703 info->screen_size = REMAPPED_FB_LEN;
704
705 strcpy(info->fix.id, "w100fb");
706 info->fix.type = FB_TYPE_PACKED_PIXELS;
707 info->fix.type_aux = 0;
708 info->fix.accel = FB_ACCEL_NONE;
709 info->fix.smem_start = mem->start+W100_FB_BASE;
710 info->fix.mmio_start = mem->start+W100_REG_BASE;
711 info->fix.mmio_len = W100_REG_LEN;
712
713 if (fb_alloc_cmap(&info->cmap, 256, 0) < 0) {
714 err = -ENOMEM;
715 goto out;
716 }
717
718 par->mode = &inf->modelist[0];
719 if(inf->init_mode & INIT_MODE_ROTATED) {
720 info->var.xres = par->mode->yres;
721 info->var.yres = par->mode->xres;
722 }
723 else {
724 info->var.xres = par->mode->xres;
725 info->var.yres = par->mode->yres;
726 }
727
728 if(inf->init_mode &= INIT_MODE_FLIPPED)
729 par->flip = 1;
730 else
731 par->flip = 0;
732
733 info->var.xres_virtual = info->var.xres;
734 info->var.yres_virtual = info->var.yres;
735 info->var.pixclock = 0x04; /* 171521; */
736 info->var.sync = 0;
737 info->var.grayscale = 0;
738 info->var.xoffset = info->var.yoffset = 0;
739 info->var.accel_flags = 0;
740 info->var.activate = FB_ACTIVATE_NOW;
741
742 w100_hw_init(par);
743
744 if (w100fb_check_var(&info->var, info) < 0) {
745 err = -EINVAL;
746 goto out;
747 }
748
749 w100fb_set_par(info);
750
751 if (register_framebuffer(info) < 0) {
752 err = -EINVAL;
753 goto out;
754 }
755
756 err = device_create_file(&pdev->dev, &dev_attr_fastpllclk);
757 err |= device_create_file(&pdev->dev, &dev_attr_reg_read);
758 err |= device_create_file(&pdev->dev, &dev_attr_reg_write);
759 err |= device_create_file(&pdev->dev, &dev_attr_flip);
760
761 if (err != 0)
762 printk(KERN_WARNING "fb%d: failed to register attributes (%d)\n",
763 info->node, err);
764
765 printk(KERN_INFO "fb%d: %s frame buffer device\n", info->node, info->fix.id);
766 return 0;
767 out:
768 fb_dealloc_cmap(&info->cmap);
769 kfree(info->pseudo_palette);
770 if (remapped_fbuf != NULL)
771 iounmap(remapped_fbuf);
772 if (remapped_regs != NULL)
773 iounmap(remapped_regs);
774 if (remapped_base != NULL)
775 iounmap(remapped_base);
776 if (info)
777 framebuffer_release(info);
778 return err;
779 }
780
781
782 static int w100fb_remove(struct platform_device *pdev)
783 {
784 struct fb_info *info = platform_get_drvdata(pdev);
785 struct w100fb_par *par=info->par;
786
787 device_remove_file(&pdev->dev, &dev_attr_fastpllclk);
788 device_remove_file(&pdev->dev, &dev_attr_reg_read);
789 device_remove_file(&pdev->dev, &dev_attr_reg_write);
790 device_remove_file(&pdev->dev, &dev_attr_flip);
791
792 unregister_framebuffer(info);
793
794 vfree(par->saved_intmem);
795 vfree(par->saved_extmem);
796 kfree(info->pseudo_palette);
797 fb_dealloc_cmap(&info->cmap);
798
799 iounmap(remapped_base);
800 iounmap(remapped_regs);
801 iounmap(remapped_fbuf);
802
803 framebuffer_release(info);
804
805 return 0;
806 }
807
808
809 /* ------------------- chipset specific functions -------------------------- */
810
811
812 static void w100_soft_reset(void)
813 {
814 u16 val = readw((u16 *) remapped_base + cfgSTATUS);
815 writew(val | 0x08, (u16 *) remapped_base + cfgSTATUS);
816 udelay(100);
817 writew(0x00, (u16 *) remapped_base + cfgSTATUS);
818 udelay(100);
819 }
820
821 static void w100_update_disable(void)
822 {
823 union disp_db_buf_cntl_wr_u disp_db_buf_wr_cntl;
824
825 /* Prevent display updates */
826 disp_db_buf_wr_cntl.f.db_buf_cntl = 0x1e;
827 disp_db_buf_wr_cntl.f.update_db_buf = 0;
828 disp_db_buf_wr_cntl.f.en_db_buf = 0;
829 writel((u32) (disp_db_buf_wr_cntl.val), remapped_regs + mmDISP_DB_BUF_CNTL);
830 }
831
832 static void w100_update_enable(void)
833 {
834 union disp_db_buf_cntl_wr_u disp_db_buf_wr_cntl;
835
836 /* Enable display updates */
837 disp_db_buf_wr_cntl.f.db_buf_cntl = 0x1e;
838 disp_db_buf_wr_cntl.f.update_db_buf = 1;
839 disp_db_buf_wr_cntl.f.en_db_buf = 1;
840 writel((u32) (disp_db_buf_wr_cntl.val), remapped_regs + mmDISP_DB_BUF_CNTL);
841 }
842
843 unsigned long w100fb_gpio_read(int port)
844 {
845 unsigned long value;
846
847 if (port==W100_GPIO_PORT_A)
848 value = readl(remapped_regs + mmGPIO_DATA);
849 else
850 value = readl(remapped_regs + mmGPIO_DATA2);
851
852 return value;
853 }
854
855 void w100fb_gpio_write(int port, unsigned long value)
856 {
857 if (port==W100_GPIO_PORT_A)
858 value = writel(value, remapped_regs + mmGPIO_DATA);
859 else
860 value = writel(value, remapped_regs + mmGPIO_DATA2);
861 }
862 EXPORT_SYMBOL(w100fb_gpio_read);
863 EXPORT_SYMBOL(w100fb_gpio_write);
864
865 /*
866 * Initialization of critical w100 hardware
867 */
868 static void w100_hw_init(struct w100fb_par *par)
869 {
870 u32 temp32;
871 union cif_cntl_u cif_cntl;
872 union intf_cntl_u intf_cntl;
873 union cfgreg_base_u cfgreg_base;
874 union wrap_top_dir_u wrap_top_dir;
875 union cif_read_dbg_u cif_read_dbg;
876 union cpu_defaults_u cpu_default;
877 union cif_write_dbg_u cif_write_dbg;
878 union wrap_start_dir_u wrap_start_dir;
879 union cif_io_u cif_io;
880 struct w100_gpio_regs *gpio = par->mach->gpio;
881
882 w100_soft_reset();
883
884 /* This is what the fpga_init code does on reset. May be wrong
885 but there is little info available */
886 writel(0x31, remapped_regs + mmSCRATCH_UMSK);
887 for (temp32 = 0; temp32 < 10000; temp32++)
888 readl(remapped_regs + mmSCRATCH_UMSK);
889 writel(0x30, remapped_regs + mmSCRATCH_UMSK);
890
891 /* Set up CIF */
892 cif_io.val = defCIF_IO;
893 writel((u32)(cif_io.val), remapped_regs + mmCIF_IO);
894
895 cif_write_dbg.val = readl(remapped_regs + mmCIF_WRITE_DBG);
896 cif_write_dbg.f.dis_packer_ful_during_rbbm_timeout = 0;
897 cif_write_dbg.f.en_dword_split_to_rbbm = 1;
898 cif_write_dbg.f.dis_timeout_during_rbbm = 1;
899 writel((u32) (cif_write_dbg.val), remapped_regs + mmCIF_WRITE_DBG);
900
901 cif_read_dbg.val = readl(remapped_regs + mmCIF_READ_DBG);
902 cif_read_dbg.f.dis_rd_same_byte_to_trig_fetch = 1;
903 writel((u32) (cif_read_dbg.val), remapped_regs + mmCIF_READ_DBG);
904
905 cif_cntl.val = readl(remapped_regs + mmCIF_CNTL);
906 cif_cntl.f.dis_system_bits = 1;
907 cif_cntl.f.dis_mr = 1;
908 cif_cntl.f.en_wait_to_compensate_dq_prop_dly = 0;
909 cif_cntl.f.intb_oe = 1;
910 cif_cntl.f.interrupt_active_high = 1;
911 writel((u32) (cif_cntl.val), remapped_regs + mmCIF_CNTL);
912
913 /* Setup cfgINTF_CNTL and cfgCPU defaults */
914 intf_cntl.val = defINTF_CNTL;
915 intf_cntl.f.ad_inc_a = 1;
916 intf_cntl.f.ad_inc_b = 1;
917 intf_cntl.f.rd_data_rdy_a = 0;
918 intf_cntl.f.rd_data_rdy_b = 0;
919 writeb((u8) (intf_cntl.val), remapped_base + cfgINTF_CNTL);
920
921 cpu_default.val = defCPU_DEFAULTS;
922 cpu_default.f.access_ind_addr_a = 1;
923 cpu_default.f.access_ind_addr_b = 1;
924 cpu_default.f.access_scratch_reg = 1;
925 cpu_default.f.transition_size = 0;
926 writeb((u8) (cpu_default.val), remapped_base + cfgCPU_DEFAULTS);
927
928 /* set up the apertures */
929 writeb((u8) (W100_REG_BASE >> 16), remapped_base + cfgREG_BASE);
930
931 cfgreg_base.val = defCFGREG_BASE;
932 cfgreg_base.f.cfgreg_base = W100_CFG_BASE;
933 writel((u32) (cfgreg_base.val), remapped_regs + mmCFGREG_BASE);
934
935 wrap_start_dir.val = defWRAP_START_DIR;
936 wrap_start_dir.f.start_addr = WRAP_BUF_BASE_VALUE >> 1;
937 writel((u32) (wrap_start_dir.val), remapped_regs + mmWRAP_START_DIR);
938
939 wrap_top_dir.val = defWRAP_TOP_DIR;
940 wrap_top_dir.f.top_addr = WRAP_BUF_TOP_VALUE >> 1;
941 writel((u32) (wrap_top_dir.val), remapped_regs + mmWRAP_TOP_DIR);
942
943 writel((u32) 0x2440, remapped_regs + mmRBBM_CNTL);
944
945 /* Set the hardware to 565 colour */
946 temp32 = readl(remapped_regs + mmDISP_DEBUG2);
947 temp32 &= 0xff7fffff;
948 temp32 |= 0x00800000;
949 writel(temp32, remapped_regs + mmDISP_DEBUG2);
950
951 /* Initialise the GPIO lines */
952 if (gpio) {
953 writel(gpio->init_data1, remapped_regs + mmGPIO_DATA);
954 writel(gpio->init_data2, remapped_regs + mmGPIO_DATA2);
955 writel(gpio->gpio_dir1, remapped_regs + mmGPIO_CNTL1);
956 writel(gpio->gpio_oe1, remapped_regs + mmGPIO_CNTL2);
957 writel(gpio->gpio_dir2, remapped_regs + mmGPIO_CNTL3);
958 writel(gpio->gpio_oe2, remapped_regs + mmGPIO_CNTL4);
959 }
960 }
961
962
963 struct power_state {
964 union clk_pin_cntl_u clk_pin_cntl;
965 union pll_ref_fb_div_u pll_ref_fb_div;
966 union pll_cntl_u pll_cntl;
967 union sclk_cntl_u sclk_cntl;
968 union pclk_cntl_u pclk_cntl;
969 union pwrmgt_cntl_u pwrmgt_cntl;
970 int auto_mode; /* system clock auto changing? */
971 };
972
973
974 static struct power_state w100_pwr_state;
975
976 /* The PLL Fout is determined by (XtalFreq/(M+1)) * ((N_int+1) + (N_fac/8)) */
977
978 /* 12.5MHz Crystal PLL Table */
979 static struct w100_pll_info xtal_12500000[] = {
980 /*freq M N_int N_fac tfgoal lock_time */
981 { 50, 0, 1, 0, 0xe0, 56}, /* 50.00 MHz */
982 { 75, 0, 5, 0, 0xde, 37}, /* 75.00 MHz */
983 {100, 0, 7, 0, 0xe0, 28}, /* 100.00 MHz */
984 {125, 0, 9, 0, 0xe0, 22}, /* 125.00 MHz */
985 {150, 0, 11, 0, 0xe0, 17}, /* 150.00 MHz */
986 { 0, 0, 0, 0, 0, 0}, /* Terminator */
987 };
988
989 /* 14.318MHz Crystal PLL Table */
990 static struct w100_pll_info xtal_14318000[] = {
991 /*freq M N_int N_fac tfgoal lock_time */
992 { 40, 4, 13, 0, 0xe0, 80}, /* tfgoal guessed */
993 { 50, 1, 6, 0, 0xe0, 64}, /* 50.05 MHz */
994 { 57, 2, 11, 0, 0xe0, 53}, /* tfgoal guessed */
995 { 75, 0, 4, 3, 0xe0, 43}, /* 75.08 MHz */
996 {100, 0, 6, 0, 0xe0, 32}, /* 100.10 MHz */
997 { 0, 0, 0, 0, 0, 0},
998 };
999
1000 /* 16MHz Crystal PLL Table */
1001 static struct w100_pll_info xtal_16000000[] = {
1002 /*freq M N_int N_fac tfgoal lock_time */
1003 { 72, 1, 8, 0, 0xe0, 48}, /* tfgoal guessed */
1004 { 95, 1, 10, 7, 0xe0, 38}, /* tfgoal guessed */
1005 { 96, 1, 11, 0, 0xe0, 36}, /* tfgoal guessed */
1006 { 0, 0, 0, 0, 0, 0},
1007 };
1008
1009 static struct pll_entries {
1010 int xtal_freq;
1011 struct w100_pll_info *pll_table;
1012 } w100_pll_tables[] = {
1013 { 12500000, &xtal_12500000[0] },
1014 { 14318000, &xtal_14318000[0] },
1015 { 16000000, &xtal_16000000[0] },
1016 { 0 },
1017 };
1018
1019 struct w100_pll_info *w100_get_xtal_table(unsigned int freq)
1020 {
1021 struct pll_entries *pll_entry = w100_pll_tables;
1022
1023 do {
1024 if (freq == pll_entry->xtal_freq)
1025 return pll_entry->pll_table;
1026 pll_entry++;
1027 } while (pll_entry->xtal_freq);
1028 return 0;
1029 }
1030
1031
1032 static unsigned int w100_get_testcount(unsigned int testclk_sel)
1033 {
1034 union clk_test_cntl_u clk_test_cntl;
1035
1036 udelay(5);
1037
1038 /* Select the test clock source and reset */
1039 clk_test_cntl.f.start_check_freq = 0x0;
1040 clk_test_cntl.f.testclk_sel = testclk_sel;
1041 clk_test_cntl.f.tstcount_rst = 0x1; /* set reset */
1042 writel((u32) (clk_test_cntl.val), remapped_regs + mmCLK_TEST_CNTL);
1043
1044 clk_test_cntl.f.tstcount_rst = 0x0; /* clear reset */
1045 writel((u32) (clk_test_cntl.val), remapped_regs + mmCLK_TEST_CNTL);
1046
1047 /* Run clock test */
1048 clk_test_cntl.f.start_check_freq = 0x1;
1049 writel((u32) (clk_test_cntl.val), remapped_regs + mmCLK_TEST_CNTL);
1050
1051 /* Give the test time to complete */
1052 udelay(20);
1053
1054 /* Return the result */
1055 clk_test_cntl.val = readl(remapped_regs + mmCLK_TEST_CNTL);
1056 clk_test_cntl.f.start_check_freq = 0x0;
1057 writel((u32) (clk_test_cntl.val), remapped_regs + mmCLK_TEST_CNTL);
1058
1059 return clk_test_cntl.f.test_count;
1060 }
1061
1062
1063 static int w100_pll_adjust(struct w100_pll_info *pll)
1064 {
1065 unsigned int tf80;
1066 unsigned int tf20;
1067
1068 /* Initial Settings */
1069 w100_pwr_state.pll_cntl.f.pll_pwdn = 0x0; /* power down */
1070 w100_pwr_state.pll_cntl.f.pll_reset = 0x0; /* not reset */
1071 w100_pwr_state.pll_cntl.f.pll_tcpoff = 0x1; /* Hi-Z */
1072 w100_pwr_state.pll_cntl.f.pll_pvg = 0x0; /* VCO gain = 0 */
1073 w100_pwr_state.pll_cntl.f.pll_vcofr = 0x0; /* VCO frequency range control = off */
1074 w100_pwr_state.pll_cntl.f.pll_ioffset = 0x0; /* current offset inside VCO = 0 */
1075 w100_pwr_state.pll_cntl.f.pll_ring_off = 0x0;
1076
1077 /* Wai Ming 80 percent of VDD 1.3V gives 1.04V, minimum operating voltage is 1.08V
1078 * therefore, commented out the following lines
1079 * tf80 meant tf100
1080 */
1081 do {
1082 /* set VCO input = 0.8 * VDD */
1083 w100_pwr_state.pll_cntl.f.pll_dactal = 0xd;
1084 writel((u32) (w100_pwr_state.pll_cntl.val), remapped_regs + mmPLL_CNTL);
1085
1086 tf80 = w100_get_testcount(TESTCLK_SRC_PLL);
1087 if (tf80 >= (pll->tfgoal)) {
1088 /* set VCO input = 0.2 * VDD */
1089 w100_pwr_state.pll_cntl.f.pll_dactal = 0x7;
1090 writel((u32) (w100_pwr_state.pll_cntl.val), remapped_regs + mmPLL_CNTL);
1091
1092 tf20 = w100_get_testcount(TESTCLK_SRC_PLL);
1093 if (tf20 <= (pll->tfgoal))
1094 return 1; /* Success */
1095
1096 if ((w100_pwr_state.pll_cntl.f.pll_vcofr == 0x0) &&
1097 ((w100_pwr_state.pll_cntl.f.pll_pvg == 0x7) ||
1098 (w100_pwr_state.pll_cntl.f.pll_ioffset == 0x0))) {
1099 /* slow VCO config */
1100 w100_pwr_state.pll_cntl.f.pll_vcofr = 0x1;
1101 w100_pwr_state.pll_cntl.f.pll_pvg = 0x0;
1102 w100_pwr_state.pll_cntl.f.pll_ioffset = 0x0;
1103 continue;
1104 }
1105 }
1106 if ((w100_pwr_state.pll_cntl.f.pll_ioffset) < 0x3) {
1107 w100_pwr_state.pll_cntl.f.pll_ioffset += 0x1;
1108 } else if ((w100_pwr_state.pll_cntl.f.pll_pvg) < 0x7) {
1109 w100_pwr_state.pll_cntl.f.pll_ioffset = 0x0;
1110 w100_pwr_state.pll_cntl.f.pll_pvg += 0x1;
1111 } else {
1112 return 0; /* Error */
1113 }
1114 } while(1);
1115 }
1116
1117
1118 /*
1119 * w100_pll_calibration
1120 */
1121 static int w100_pll_calibration(struct w100_pll_info *pll)
1122 {
1123 int status;
1124
1125 status = w100_pll_adjust(pll);
1126
1127 /* PLL Reset And Lock */
1128 /* set VCO input = 0.5 * VDD */
1129 w100_pwr_state.pll_cntl.f.pll_dactal = 0xa;
1130 writel((u32) (w100_pwr_state.pll_cntl.val), remapped_regs + mmPLL_CNTL);
1131
1132 udelay(1); /* reset time */
1133
1134 /* enable charge pump */
1135 w100_pwr_state.pll_cntl.f.pll_tcpoff = 0x0; /* normal */
1136 writel((u32) (w100_pwr_state.pll_cntl.val), remapped_regs + mmPLL_CNTL);
1137
1138 /* set VCO input = Hi-Z, disable DAC */
1139 w100_pwr_state.pll_cntl.f.pll_dactal = 0x0;
1140 writel((u32) (w100_pwr_state.pll_cntl.val), remapped_regs + mmPLL_CNTL);
1141
1142 udelay(400); /* lock time */
1143
1144 /* PLL locked */
1145
1146 return status;
1147 }
1148
1149
1150 static int w100_pll_set_clk(struct w100_pll_info *pll)
1151 {
1152 int status;
1153
1154 if (w100_pwr_state.auto_mode == 1) /* auto mode */
1155 {
1156 w100_pwr_state.pwrmgt_cntl.f.pwm_fast_noml_hw_en = 0x0; /* disable fast to normal */
1157 w100_pwr_state.pwrmgt_cntl.f.pwm_noml_fast_hw_en = 0x0; /* disable normal to fast */
1158 writel((u32) (w100_pwr_state.pwrmgt_cntl.val), remapped_regs + mmPWRMGT_CNTL);
1159 }
1160
1161 /* Set system clock source to XTAL whilst adjusting the PLL! */
1162 w100_pwr_state.sclk_cntl.f.sclk_src_sel = CLK_SRC_XTAL;
1163 writel((u32) (w100_pwr_state.sclk_cntl.val), remapped_regs + mmSCLK_CNTL);
1164
1165 w100_pwr_state.pll_ref_fb_div.f.pll_ref_div = pll->M;
1166 w100_pwr_state.pll_ref_fb_div.f.pll_fb_div_int = pll->N_int;
1167 w100_pwr_state.pll_ref_fb_div.f.pll_fb_div_frac = pll->N_fac;
1168 w100_pwr_state.pll_ref_fb_div.f.pll_lock_time = pll->lock_time;
1169 writel((u32) (w100_pwr_state.pll_ref_fb_div.val), remapped_regs + mmPLL_REF_FB_DIV);
1170
1171 w100_pwr_state.pwrmgt_cntl.f.pwm_mode_req = 0;
1172 writel((u32) (w100_pwr_state.pwrmgt_cntl.val), remapped_regs + mmPWRMGT_CNTL);
1173
1174 status = w100_pll_calibration(pll);
1175
1176 if (w100_pwr_state.auto_mode == 1) /* auto mode */
1177 {
1178 w100_pwr_state.pwrmgt_cntl.f.pwm_fast_noml_hw_en = 0x1; /* reenable fast to normal */
1179 w100_pwr_state.pwrmgt_cntl.f.pwm_noml_fast_hw_en = 0x1; /* reenable normal to fast */
1180 writel((u32) (w100_pwr_state.pwrmgt_cntl.val), remapped_regs + mmPWRMGT_CNTL);
1181 }
1182 return status;
1183 }
1184
1185 /* freq = target frequency of the PLL */
1186 static int w100_set_pll_freq(struct w100fb_par *par, unsigned int freq)
1187 {
1188 struct w100_pll_info *pll = par->pll_table;
1189
1190 do {
1191 if (freq == pll->freq) {
1192 return w100_pll_set_clk(pll);
1193 }
1194 pll++;
1195 } while(pll->freq);
1196 return 0;
1197 }
1198
1199 /* Set up an initial state. Some values/fields set
1200 here will be overwritten. */
1201 static void w100_pwm_setup(struct w100fb_par *par)
1202 {
1203 w100_pwr_state.clk_pin_cntl.f.osc_en = 0x1;
1204 w100_pwr_state.clk_pin_cntl.f.osc_gain = 0x1f;
1205 w100_pwr_state.clk_pin_cntl.f.dont_use_xtalin = 0x0;
1206 w100_pwr_state.clk_pin_cntl.f.xtalin_pm_en = 0x0;
1207 w100_pwr_state.clk_pin_cntl.f.xtalin_dbl_en = par->mach->xtal_dbl ? 1 : 0;
1208 w100_pwr_state.clk_pin_cntl.f.cg_debug = 0x0;
1209 writel((u32) (w100_pwr_state.clk_pin_cntl.val), remapped_regs + mmCLK_PIN_CNTL);
1210
1211 w100_pwr_state.sclk_cntl.f.sclk_src_sel = CLK_SRC_XTAL;
1212 w100_pwr_state.sclk_cntl.f.sclk_post_div_fast = 0x0; /* Pfast = 1 */
1213 w100_pwr_state.sclk_cntl.f.sclk_clkon_hys = 0x3;
1214 w100_pwr_state.sclk_cntl.f.sclk_post_div_slow = 0x0; /* Pslow = 1 */
1215 w100_pwr_state.sclk_cntl.f.disp_cg_ok2switch_en = 0x0;
1216 w100_pwr_state.sclk_cntl.f.sclk_force_reg = 0x0; /* Dynamic */
1217 w100_pwr_state.sclk_cntl.f.sclk_force_disp = 0x0; /* Dynamic */
1218 w100_pwr_state.sclk_cntl.f.sclk_force_mc = 0x0; /* Dynamic */
1219 w100_pwr_state.sclk_cntl.f.sclk_force_extmc = 0x0; /* Dynamic */
1220 w100_pwr_state.sclk_cntl.f.sclk_force_cp = 0x0; /* Dynamic */
1221 w100_pwr_state.sclk_cntl.f.sclk_force_e2 = 0x0; /* Dynamic */
1222 w100_pwr_state.sclk_cntl.f.sclk_force_e3 = 0x0; /* Dynamic */
1223 w100_pwr_state.sclk_cntl.f.sclk_force_idct = 0x0; /* Dynamic */
1224 w100_pwr_state.sclk_cntl.f.sclk_force_bist = 0x0; /* Dynamic */
1225 w100_pwr_state.sclk_cntl.f.busy_extend_cp = 0x0;
1226 w100_pwr_state.sclk_cntl.f.busy_extend_e2 = 0x0;
1227 w100_pwr_state.sclk_cntl.f.busy_extend_e3 = 0x0;
1228 w100_pwr_state.sclk_cntl.f.busy_extend_idct = 0x0;
1229 writel((u32) (w100_pwr_state.sclk_cntl.val), remapped_regs + mmSCLK_CNTL);
1230
1231 w100_pwr_state.pclk_cntl.f.pclk_src_sel = CLK_SRC_XTAL;
1232 w100_pwr_state.pclk_cntl.f.pclk_post_div = 0x1; /* P = 2 */
1233 w100_pwr_state.pclk_cntl.f.pclk_force_disp = 0x0; /* Dynamic */
1234 writel((u32) (w100_pwr_state.pclk_cntl.val), remapped_regs + mmPCLK_CNTL);
1235
1236 w100_pwr_state.pll_ref_fb_div.f.pll_ref_div = 0x0; /* M = 1 */
1237 w100_pwr_state.pll_ref_fb_div.f.pll_fb_div_int = 0x0; /* N = 1.0 */
1238 w100_pwr_state.pll_ref_fb_div.f.pll_fb_div_frac = 0x0;
1239 w100_pwr_state.pll_ref_fb_div.f.pll_reset_time = 0x5;
1240 w100_pwr_state.pll_ref_fb_div.f.pll_lock_time = 0xff;
1241 writel((u32) (w100_pwr_state.pll_ref_fb_div.val), remapped_regs + mmPLL_REF_FB_DIV);
1242
1243 w100_pwr_state.pll_cntl.f.pll_pwdn = 0x1;
1244 w100_pwr_state.pll_cntl.f.pll_reset = 0x1;
1245 w100_pwr_state.pll_cntl.f.pll_pm_en = 0x0;
1246 w100_pwr_state.pll_cntl.f.pll_mode = 0x0; /* uses VCO clock */
1247 w100_pwr_state.pll_cntl.f.pll_refclk_sel = 0x0;
1248 w100_pwr_state.pll_cntl.f.pll_fbclk_sel = 0x0;
1249 w100_pwr_state.pll_cntl.f.pll_tcpoff = 0x0;
1250 w100_pwr_state.pll_cntl.f.pll_pcp = 0x4;
1251 w100_pwr_state.pll_cntl.f.pll_pvg = 0x0;
1252 w100_pwr_state.pll_cntl.f.pll_vcofr = 0x0;
1253 w100_pwr_state.pll_cntl.f.pll_ioffset = 0x0;
1254 w100_pwr_state.pll_cntl.f.pll_pecc_mode = 0x0;
1255 w100_pwr_state.pll_cntl.f.pll_pecc_scon = 0x0;
1256 w100_pwr_state.pll_cntl.f.pll_dactal = 0x0; /* Hi-Z */
1257 w100_pwr_state.pll_cntl.f.pll_cp_clip = 0x3;
1258 w100_pwr_state.pll_cntl.f.pll_conf = 0x2;
1259 w100_pwr_state.pll_cntl.f.pll_mbctrl = 0x2;
1260 w100_pwr_state.pll_cntl.f.pll_ring_off = 0x0;
1261 writel((u32) (w100_pwr_state.pll_cntl.val), remapped_regs + mmPLL_CNTL);
1262
1263 w100_pwr_state.pwrmgt_cntl.f.pwm_enable = 0x0;
1264 w100_pwr_state.pwrmgt_cntl.f.pwm_mode_req = 0x1; /* normal mode (0, 1, 3) */
1265 w100_pwr_state.pwrmgt_cntl.f.pwm_wakeup_cond = 0x0;
1266 w100_pwr_state.pwrmgt_cntl.f.pwm_fast_noml_hw_en = 0x0;
1267 w100_pwr_state.pwrmgt_cntl.f.pwm_noml_fast_hw_en = 0x0;
1268 w100_pwr_state.pwrmgt_cntl.f.pwm_fast_noml_cond = 0x1; /* PM4,ENG */
1269 w100_pwr_state.pwrmgt_cntl.f.pwm_noml_fast_cond = 0x1; /* PM4,ENG */
1270 w100_pwr_state.pwrmgt_cntl.f.pwm_idle_timer = 0xFF;
1271 w100_pwr_state.pwrmgt_cntl.f.pwm_busy_timer = 0xFF;
1272 writel((u32) (w100_pwr_state.pwrmgt_cntl.val), remapped_regs + mmPWRMGT_CNTL);
1273
1274 w100_pwr_state.auto_mode = 0; /* manual mode */
1275 }
1276
1277
1278 /*
1279 * Setup the w100 clocks for the specified mode
1280 */
1281 static void w100_init_clocks(struct w100fb_par *par)
1282 {
1283 struct w100_mode *mode = par->mode;
1284
1285 if (mode->pixclk_src == CLK_SRC_PLL || mode->sysclk_src == CLK_SRC_PLL)
1286 w100_set_pll_freq(par, (par->fastpll_mode && mode->fast_pll_freq) ? mode->fast_pll_freq : mode->pll_freq);
1287
1288 w100_pwr_state.sclk_cntl.f.sclk_src_sel = mode->sysclk_src;
1289 w100_pwr_state.sclk_cntl.f.sclk_post_div_fast = mode->sysclk_divider;
1290 w100_pwr_state.sclk_cntl.f.sclk_post_div_slow = mode->sysclk_divider;
1291 writel((u32) (w100_pwr_state.sclk_cntl.val), remapped_regs + mmSCLK_CNTL);
1292 }
1293
1294 static void w100_init_lcd(struct w100fb_par *par)
1295 {
1296 u32 temp32;
1297 struct w100_mode *mode = par->mode;
1298 struct w100_gen_regs *regs = par->mach->regs;
1299 union active_h_disp_u active_h_disp;
1300 union active_v_disp_u active_v_disp;
1301 union graphic_h_disp_u graphic_h_disp;
1302 union graphic_v_disp_u graphic_v_disp;
1303 union crtc_total_u crtc_total;
1304
1305 /* w3200 doesnt like undefined bits being set so zero register values first */
1306
1307 active_h_disp.val = 0;
1308 active_h_disp.f.active_h_start=mode->left_margin;
1309 active_h_disp.f.active_h_end=mode->left_margin + mode->xres;
1310 writel(active_h_disp.val, remapped_regs + mmACTIVE_H_DISP);
1311
1312 active_v_disp.val = 0;
1313 active_v_disp.f.active_v_start=mode->upper_margin;
1314 active_v_disp.f.active_v_end=mode->upper_margin + mode->yres;
1315 writel(active_v_disp.val, remapped_regs + mmACTIVE_V_DISP);
1316
1317 graphic_h_disp.val = 0;
1318 graphic_h_disp.f.graphic_h_start=mode->left_margin;
1319 graphic_h_disp.f.graphic_h_end=mode->left_margin + mode->xres;
1320 writel(graphic_h_disp.val, remapped_regs + mmGRAPHIC_H_DISP);
1321
1322 graphic_v_disp.val = 0;
1323 graphic_v_disp.f.graphic_v_start=mode->upper_margin;
1324 graphic_v_disp.f.graphic_v_end=mode->upper_margin + mode->yres;
1325 writel(graphic_v_disp.val, remapped_regs + mmGRAPHIC_V_DISP);
1326
1327 crtc_total.val = 0;
1328 crtc_total.f.crtc_h_total=mode->left_margin + mode->xres + mode->right_margin;
1329 crtc_total.f.crtc_v_total=mode->upper_margin + mode->yres + mode->lower_margin;
1330 writel(crtc_total.val, remapped_regs + mmCRTC_TOTAL);
1331
1332 writel(mode->crtc_ss, remapped_regs + mmCRTC_SS);
1333 writel(mode->crtc_ls, remapped_regs + mmCRTC_LS);
1334 writel(mode->crtc_gs, remapped_regs + mmCRTC_GS);
1335 writel(mode->crtc_vpos_gs, remapped_regs + mmCRTC_VPOS_GS);
1336 writel(mode->crtc_rev, remapped_regs + mmCRTC_REV);
1337 writel(mode->crtc_dclk, remapped_regs + mmCRTC_DCLK);
1338 writel(mode->crtc_gclk, remapped_regs + mmCRTC_GCLK);
1339 writel(mode->crtc_goe, remapped_regs + mmCRTC_GOE);
1340 writel(mode->crtc_ps1_active, remapped_regs + mmCRTC_PS1_ACTIVE);
1341
1342 writel(regs->lcd_format, remapped_regs + mmLCD_FORMAT);
1343 writel(regs->lcdd_cntl1, remapped_regs + mmLCDD_CNTL1);
1344 writel(regs->lcdd_cntl2, remapped_regs + mmLCDD_CNTL2);
1345 writel(regs->genlcd_cntl1, remapped_regs + mmGENLCD_CNTL1);
1346 writel(regs->genlcd_cntl2, remapped_regs + mmGENLCD_CNTL2);
1347 writel(regs->genlcd_cntl3, remapped_regs + mmGENLCD_CNTL3);
1348
1349 writel(0x00000000, remapped_regs + mmCRTC_FRAME);
1350 writel(0x00000000, remapped_regs + mmCRTC_FRAME_VPOS);
1351 writel(0x00000000, remapped_regs + mmCRTC_DEFAULT_COUNT);
1352 writel(0x0000FF00, remapped_regs + mmLCD_BACKGROUND_COLOR);
1353
1354 /* Hack for overlay in ext memory */
1355 temp32 = readl(remapped_regs + mmDISP_DEBUG2);
1356 temp32 |= 0xc0000000;
1357 writel(temp32, remapped_regs + mmDISP_DEBUG2);
1358 }
1359
1360
1361 static void w100_setup_memory(struct w100fb_par *par)
1362 {
1363 union mc_ext_mem_location_u extmem_location;
1364 union mc_fb_location_u intmem_location;
1365 struct w100_mem_info *mem = par->mach->mem;
1366 struct w100_bm_mem_info *bm_mem = par->mach->bm_mem;
1367
1368 if (!par->extmem_active) {
1369 w100_suspend(W100_SUSPEND_EXTMEM);
1370
1371 /* Map Internal Memory at FB Base */
1372 intmem_location.f.mc_fb_start = W100_FB_BASE >> 8;
1373 intmem_location.f.mc_fb_top = (W100_FB_BASE+MEM_INT_SIZE) >> 8;
1374 writel((u32) (intmem_location.val), remapped_regs + mmMC_FB_LOCATION);
1375
1376 /* Unmap External Memory - value is *probably* irrelevant but may have meaning
1377 to acceleration libraries */
1378 extmem_location.f.mc_ext_mem_start = MEM_EXT_BASE_VALUE >> 8;
1379 extmem_location.f.mc_ext_mem_top = (MEM_EXT_BASE_VALUE-1) >> 8;
1380 writel((u32) (extmem_location.val), remapped_regs + mmMC_EXT_MEM_LOCATION);
1381 } else {
1382 /* Map Internal Memory to its default location */
1383 intmem_location.f.mc_fb_start = MEM_INT_BASE_VALUE >> 8;
1384 intmem_location.f.mc_fb_top = (MEM_INT_BASE_VALUE+MEM_INT_SIZE) >> 8;
1385 writel((u32) (intmem_location.val), remapped_regs + mmMC_FB_LOCATION);
1386
1387 /* Map External Memory at FB Base */
1388 extmem_location.f.mc_ext_mem_start = W100_FB_BASE >> 8;
1389 extmem_location.f.mc_ext_mem_top = (W100_FB_BASE+par->mach->mem->size) >> 8;
1390 writel((u32) (extmem_location.val), remapped_regs + mmMC_EXT_MEM_LOCATION);
1391
1392 writel(0x00007800, remapped_regs + mmMC_BIST_CTRL);
1393 writel(mem->ext_cntl, remapped_regs + mmMEM_EXT_CNTL);
1394 writel(0x00200021, remapped_regs + mmMEM_SDRAM_MODE_REG);
1395 udelay(100);
1396 writel(0x80200021, remapped_regs + mmMEM_SDRAM_MODE_REG);
1397 udelay(100);
1398 writel(mem->sdram_mode_reg, remapped_regs + mmMEM_SDRAM_MODE_REG);
1399 udelay(100);
1400 writel(mem->ext_timing_cntl, remapped_regs + mmMEM_EXT_TIMING_CNTL);
1401 writel(mem->io_cntl, remapped_regs + mmMEM_IO_CNTL);
1402 if (bm_mem) {
1403 writel(bm_mem->ext_mem_bw, remapped_regs + mmBM_EXT_MEM_BANDWIDTH);
1404 writel(bm_mem->offset, remapped_regs + mmBM_OFFSET);
1405 writel(bm_mem->ext_timing_ctl, remapped_regs + mmBM_MEM_EXT_TIMING_CNTL);
1406 writel(bm_mem->ext_cntl, remapped_regs + mmBM_MEM_EXT_CNTL);
1407 writel(bm_mem->mode_reg, remapped_regs + mmBM_MEM_MODE_REG);
1408 writel(bm_mem->io_cntl, remapped_regs + mmBM_MEM_IO_CNTL);
1409 writel(bm_mem->config, remapped_regs + mmBM_CONFIG);
1410 }
1411 }
1412 }
1413
1414 static void w100_set_dispregs(struct w100fb_par *par)
1415 {
1416 unsigned long rot=0, divider, offset=0;
1417 union graphic_ctrl_u graphic_ctrl;
1418
1419 /* See if the mode has been rotated */
1420 if (par->xres == par->mode->xres) {
1421 if (par->flip) {
1422 rot=3; /* 180 degree */
1423 offset=(par->xres * par->yres) - 1;
1424 } /* else 0 degree */
1425 divider = par->mode->pixclk_divider;
1426 } else {
1427 if (par->flip) {
1428 rot=2; /* 270 degree */
1429 offset=par->xres - 1;
1430 } else {
1431 rot=1; /* 90 degree */
1432 offset=par->xres * (par->yres - 1);
1433 }
1434 divider = par->mode->pixclk_divider_rotated;
1435 }
1436
1437 graphic_ctrl.val = 0; /* w32xx doesn't like undefined bits */
1438 switch (par->chip_id) {
1439 case CHIP_ID_W100:
1440 graphic_ctrl.f_w100.color_depth=6;
1441 graphic_ctrl.f_w100.en_crtc=1;
1442 graphic_ctrl.f_w100.en_graphic_req=1;
1443 graphic_ctrl.f_w100.en_graphic_crtc=1;
1444 graphic_ctrl.f_w100.lcd_pclk_on=1;
1445 graphic_ctrl.f_w100.lcd_sclk_on=1;
1446 graphic_ctrl.f_w100.low_power_on=0;
1447 graphic_ctrl.f_w100.req_freq=0;
1448 graphic_ctrl.f_w100.portrait_mode=rot;
1449
1450 /* Zaurus needs this */
1451 switch(par->xres) {
1452 case 240:
1453 case 320:
1454 default:
1455 graphic_ctrl.f_w100.total_req_graphic=0xa0;
1456 break;
1457 case 480:
1458 case 640:
1459 switch(rot) {
1460 case 0: /* 0 */
1461 case 3: /* 180 */
1462 graphic_ctrl.f_w100.low_power_on=1;
1463 graphic_ctrl.f_w100.req_freq=5;
1464 break;
1465 case 1: /* 90 */
1466 case 2: /* 270 */
1467 graphic_ctrl.f_w100.req_freq=4;
1468 break;
1469 default:
1470 break;
1471 }
1472 graphic_ctrl.f_w100.total_req_graphic=0xf0;
1473 break;
1474 }
1475 break;
1476 case CHIP_ID_W3200:
1477 case CHIP_ID_W3220:
1478 graphic_ctrl.f_w32xx.color_depth=6;
1479 graphic_ctrl.f_w32xx.en_crtc=1;
1480 graphic_ctrl.f_w32xx.en_graphic_req=1;
1481 graphic_ctrl.f_w32xx.en_graphic_crtc=1;
1482 graphic_ctrl.f_w32xx.lcd_pclk_on=1;
1483 graphic_ctrl.f_w32xx.lcd_sclk_on=1;
1484 graphic_ctrl.f_w32xx.low_power_on=0;
1485 graphic_ctrl.f_w32xx.req_freq=0;
1486 graphic_ctrl.f_w32xx.total_req_graphic=par->mode->xres >> 1; /* panel xres, not mode */
1487 graphic_ctrl.f_w32xx.portrait_mode=rot;
1488 break;
1489 }
1490
1491 /* Set the pixel clock source and divider */
1492 w100_pwr_state.pclk_cntl.f.pclk_src_sel = par->mode->pixclk_src;
1493 w100_pwr_state.pclk_cntl.f.pclk_post_div = divider;
1494 writel((u32) (w100_pwr_state.pclk_cntl.val), remapped_regs + mmPCLK_CNTL);
1495
1496 writel(graphic_ctrl.val, remapped_regs + mmGRAPHIC_CTRL);
1497 writel(W100_FB_BASE + ((offset * BITS_PER_PIXEL/8)&~0x03UL), remapped_regs + mmGRAPHIC_OFFSET);
1498 writel((par->xres*BITS_PER_PIXEL/8), remapped_regs + mmGRAPHIC_PITCH);
1499 }
1500
1501
1502 /*
1503 * Work out how long the sync pulse lasts
1504 * Value is 1/(time in seconds)
1505 */
1506 static void calc_hsync(struct w100fb_par *par)
1507 {
1508 unsigned long hsync;
1509 struct w100_mode *mode = par->mode;
1510 union crtc_ss_u crtc_ss;
1511
1512 if (mode->pixclk_src == CLK_SRC_XTAL)
1513 hsync=par->mach->xtal_freq;
1514 else
1515 hsync=((par->fastpll_mode && mode->fast_pll_freq) ? mode->fast_pll_freq : mode->pll_freq)*100000;
1516
1517 hsync /= (w100_pwr_state.pclk_cntl.f.pclk_post_div + 1);
1518
1519 crtc_ss.val = readl(remapped_regs + mmCRTC_SS);
1520 if (crtc_ss.val)
1521 par->hsync_len = hsync / (crtc_ss.f.ss_end-crtc_ss.f.ss_start);
1522 else
1523 par->hsync_len = 0;
1524 }
1525
1526 static void w100_suspend(u32 mode)
1527 {
1528 u32 val;
1529
1530 writel(0x7FFF8000, remapped_regs + mmMC_EXT_MEM_LOCATION);
1531 writel(0x00FF0000, remapped_regs + mmMC_PERF_MON_CNTL);
1532
1533 val = readl(remapped_regs + mmMEM_EXT_TIMING_CNTL);
1534 val &= ~(0x00100000); /* bit20=0 */
1535 val |= 0xFF000000; /* bit31:24=0xff */
1536 writel(val, remapped_regs + mmMEM_EXT_TIMING_CNTL);
1537
1538 val = readl(remapped_regs + mmMEM_EXT_CNTL);
1539 val &= ~(0x00040000); /* bit18=0 */
1540 val |= 0x00080000; /* bit19=1 */
1541 writel(val, remapped_regs + mmMEM_EXT_CNTL);
1542
1543 udelay(1); /* wait 1us */
1544
1545 if (mode == W100_SUSPEND_EXTMEM) {
1546 /* CKE: Tri-State */
1547 val = readl(remapped_regs + mmMEM_EXT_CNTL);
1548 val |= 0x40000000; /* bit30=1 */
1549 writel(val, remapped_regs + mmMEM_EXT_CNTL);
1550
1551 /* CLK: Stop */
1552 val = readl(remapped_regs + mmMEM_EXT_CNTL);
1553 val &= ~(0x00000001); /* bit0=0 */
1554 writel(val, remapped_regs + mmMEM_EXT_CNTL);
1555 } else {
1556 writel(0x00000000, remapped_regs + mmSCLK_CNTL);
1557 writel(0x000000BF, remapped_regs + mmCLK_PIN_CNTL);
1558 writel(0x00000015, remapped_regs + mmPWRMGT_CNTL);
1559
1560 udelay(5);
1561
1562 val = readl(remapped_regs + mmPLL_CNTL);
1563 val |= 0x00000004; /* bit2=1 */
1564 writel(val, remapped_regs + mmPLL_CNTL);
1565 writel(0x0000001d, remapped_regs + mmPWRMGT_CNTL);
1566 }
1567 }
1568
1569 static void w100_vsync(void)
1570 {
1571 u32 tmp;
1572 int timeout = 30000; /* VSync timeout = 30[ms] > 16.8[ms] */
1573
1574 tmp = readl(remapped_regs + mmACTIVE_V_DISP);
1575
1576 /* set vline pos */
1577 writel((tmp >> 16) & 0x3ff, remapped_regs + mmDISP_INT_CNTL);
1578
1579 /* disable vline irq */
1580 tmp = readl(remapped_regs + mmGEN_INT_CNTL);
1581
1582 tmp &= ~0x00000002;
1583 writel(tmp, remapped_regs + mmGEN_INT_CNTL);
1584
1585 /* clear vline irq status */
1586 writel(0x00000002, remapped_regs + mmGEN_INT_STATUS);
1587
1588 /* enable vline irq */
1589 writel((tmp | 0x00000002), remapped_regs + mmGEN_INT_CNTL);
1590
1591 /* clear vline irq status */
1592 writel(0x00000002, remapped_regs + mmGEN_INT_STATUS);
1593
1594 while(timeout > 0) {
1595 if (readl(remapped_regs + mmGEN_INT_STATUS) & 0x00000002)
1596 break;
1597 udelay(1);
1598 timeout--;
1599 }
1600
1601 /* disable vline irq */
1602 writel(tmp, remapped_regs + mmGEN_INT_CNTL);
1603
1604 /* clear vline irq status */
1605 writel(0x00000002, remapped_regs + mmGEN_INT_STATUS);
1606 }
1607
1608 static struct platform_driver w100fb_driver = {
1609 .probe = w100fb_probe,
1610 .remove = w100fb_remove,
1611 .suspend = w100fb_suspend,
1612 .resume = w100fb_resume,
1613 .driver = {
1614 .name = "w100fb",
1615 },
1616 };
1617
1618 int __devinit w100fb_init(void)
1619 {
1620 return platform_driver_register(&w100fb_driver);
1621 }
1622
1623 void __exit w100fb_cleanup(void)
1624 {
1625 platform_driver_unregister(&w100fb_driver);
1626 }
1627
1628 module_init(w100fb_init);
1629 module_exit(w100fb_cleanup);
1630
1631 MODULE_DESCRIPTION("ATI Imageon w100 framebuffer driver");
1632 MODULE_LICENSE("GPL");
This page took 0.166752 seconds and 5 git commands to generate.