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