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);
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 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 = dev_get_platdata(&pdev->dev);
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 		fb_warn(info, "failed to register attributes (%d)\n", err);
765 
766 	fb_info(info, "%s frame buffer device\n", info->fix.id);
767 	return 0;
768 out:
769 	if (info) {
770 		fb_dealloc_cmap(&info->cmap);
771 		kfree(info->pseudo_palette);
772 	}
773 	if (remapped_fbuf != NULL)
774 		iounmap(remapped_fbuf);
775 	if (remapped_regs != NULL)
776 		iounmap(remapped_regs);
777 	if (remapped_base != NULL)
778 		iounmap(remapped_base);
779 	if (info)
780 		framebuffer_release(info);
781 	return err;
782 }
783 
784 
w100fb_remove(struct platform_device * pdev)785 static int w100fb_remove(struct platform_device *pdev)
786 {
787 	struct fb_info *info = platform_get_drvdata(pdev);
788 	struct w100fb_par *par=info->par;
789 
790 	device_remove_file(&pdev->dev, &dev_attr_fastpllclk);
791 	device_remove_file(&pdev->dev, &dev_attr_reg_read);
792 	device_remove_file(&pdev->dev, &dev_attr_reg_write);
793 	device_remove_file(&pdev->dev, &dev_attr_flip);
794 
795 	unregister_framebuffer(info);
796 
797 	vfree(par->saved_intmem);
798 	vfree(par->saved_extmem);
799 	kfree(info->pseudo_palette);
800 	fb_dealloc_cmap(&info->cmap);
801 
802 	iounmap(remapped_base);
803 	iounmap(remapped_regs);
804 	iounmap(remapped_fbuf);
805 
806 	framebuffer_release(info);
807 
808 	return 0;
809 }
810 
811 
812 /* ------------------- chipset specific functions -------------------------- */
813 
814 
w100_soft_reset(void)815 static void w100_soft_reset(void)
816 {
817 	u16 val = readw((u16 *) remapped_base + cfgSTATUS);
818 	writew(val | 0x08, (u16 *) remapped_base + cfgSTATUS);
819 	udelay(100);
820 	writew(0x00, (u16 *) remapped_base + cfgSTATUS);
821 	udelay(100);
822 }
823 
w100_update_disable(void)824 static void w100_update_disable(void)
825 {
826 	union disp_db_buf_cntl_wr_u disp_db_buf_wr_cntl;
827 
828 	/* Prevent display updates */
829 	disp_db_buf_wr_cntl.f.db_buf_cntl = 0x1e;
830 	disp_db_buf_wr_cntl.f.update_db_buf = 0;
831 	disp_db_buf_wr_cntl.f.en_db_buf = 0;
832 	writel((u32) (disp_db_buf_wr_cntl.val), remapped_regs + mmDISP_DB_BUF_CNTL);
833 }
834 
w100_update_enable(void)835 static void w100_update_enable(void)
836 {
837 	union disp_db_buf_cntl_wr_u disp_db_buf_wr_cntl;
838 
839 	/* Enable display updates */
840 	disp_db_buf_wr_cntl.f.db_buf_cntl = 0x1e;
841 	disp_db_buf_wr_cntl.f.update_db_buf = 1;
842 	disp_db_buf_wr_cntl.f.en_db_buf = 1;
843 	writel((u32) (disp_db_buf_wr_cntl.val), remapped_regs + mmDISP_DB_BUF_CNTL);
844 }
845 
w100fb_gpio_read(int port)846 unsigned long w100fb_gpio_read(int port)
847 {
848 	unsigned long value;
849 
850 	if (port==W100_GPIO_PORT_A)
851 		value = readl(remapped_regs + mmGPIO_DATA);
852 	else
853 		value = readl(remapped_regs + mmGPIO_DATA2);
854 
855 	return value;
856 }
857 
w100fb_gpio_write(int port,unsigned long value)858 void w100fb_gpio_write(int port, unsigned long value)
859 {
860 	if (port==W100_GPIO_PORT_A)
861 		writel(value, remapped_regs + mmGPIO_DATA);
862 	else
863 		writel(value, remapped_regs + mmGPIO_DATA2);
864 }
865 EXPORT_SYMBOL(w100fb_gpio_read);
866 EXPORT_SYMBOL(w100fb_gpio_write);
867 
868 /*
869  * Initialization of critical w100 hardware
870  */
w100_hw_init(struct w100fb_par * par)871 static void w100_hw_init(struct w100fb_par *par)
872 {
873 	u32 temp32;
874 	union cif_cntl_u cif_cntl;
875 	union intf_cntl_u intf_cntl;
876 	union cfgreg_base_u cfgreg_base;
877 	union wrap_top_dir_u wrap_top_dir;
878 	union cif_read_dbg_u cif_read_dbg;
879 	union cpu_defaults_u cpu_default;
880 	union cif_write_dbg_u cif_write_dbg;
881 	union wrap_start_dir_u wrap_start_dir;
882 	union cif_io_u cif_io;
883 	struct w100_gpio_regs *gpio = par->mach->gpio;
884 
885 	w100_soft_reset();
886 
887 	/* This is what the fpga_init code does on reset. May be wrong
888 	   but there is little info available */
889 	writel(0x31, remapped_regs + mmSCRATCH_UMSK);
890 	for (temp32 = 0; temp32 < 10000; temp32++)
891 		readl(remapped_regs + mmSCRATCH_UMSK);
892 	writel(0x30, remapped_regs + mmSCRATCH_UMSK);
893 
894 	/* Set up CIF */
895 	cif_io.val = defCIF_IO;
896 	writel((u32)(cif_io.val), remapped_regs + mmCIF_IO);
897 
898 	cif_write_dbg.val = readl(remapped_regs + mmCIF_WRITE_DBG);
899 	cif_write_dbg.f.dis_packer_ful_during_rbbm_timeout = 0;
900 	cif_write_dbg.f.en_dword_split_to_rbbm = 1;
901 	cif_write_dbg.f.dis_timeout_during_rbbm = 1;
902 	writel((u32) (cif_write_dbg.val), remapped_regs + mmCIF_WRITE_DBG);
903 
904 	cif_read_dbg.val = readl(remapped_regs + mmCIF_READ_DBG);
905 	cif_read_dbg.f.dis_rd_same_byte_to_trig_fetch = 1;
906 	writel((u32) (cif_read_dbg.val), remapped_regs + mmCIF_READ_DBG);
907 
908 	cif_cntl.val = readl(remapped_regs + mmCIF_CNTL);
909 	cif_cntl.f.dis_system_bits = 1;
910 	cif_cntl.f.dis_mr = 1;
911 	cif_cntl.f.en_wait_to_compensate_dq_prop_dly = 0;
912 	cif_cntl.f.intb_oe = 1;
913 	cif_cntl.f.interrupt_active_high = 1;
914 	writel((u32) (cif_cntl.val), remapped_regs + mmCIF_CNTL);
915 
916 	/* Setup cfgINTF_CNTL and cfgCPU defaults */
917 	intf_cntl.val = defINTF_CNTL;
918 	intf_cntl.f.ad_inc_a = 1;
919 	intf_cntl.f.ad_inc_b = 1;
920 	intf_cntl.f.rd_data_rdy_a = 0;
921 	intf_cntl.f.rd_data_rdy_b = 0;
922 	writeb((u8) (intf_cntl.val), remapped_base + cfgINTF_CNTL);
923 
924 	cpu_default.val = defCPU_DEFAULTS;
925 	cpu_default.f.access_ind_addr_a = 1;
926 	cpu_default.f.access_ind_addr_b = 1;
927 	cpu_default.f.access_scratch_reg = 1;
928 	cpu_default.f.transition_size = 0;
929 	writeb((u8) (cpu_default.val), remapped_base + cfgCPU_DEFAULTS);
930 
931 	/* set up the apertures */
932 	writeb((u8) (W100_REG_BASE >> 16), remapped_base + cfgREG_BASE);
933 
934 	cfgreg_base.val = defCFGREG_BASE;
935 	cfgreg_base.f.cfgreg_base = W100_CFG_BASE;
936 	writel((u32) (cfgreg_base.val), remapped_regs + mmCFGREG_BASE);
937 
938 	wrap_start_dir.val = defWRAP_START_DIR;
939 	wrap_start_dir.f.start_addr = WRAP_BUF_BASE_VALUE >> 1;
940 	writel((u32) (wrap_start_dir.val), remapped_regs + mmWRAP_START_DIR);
941 
942 	wrap_top_dir.val = defWRAP_TOP_DIR;
943 	wrap_top_dir.f.top_addr = WRAP_BUF_TOP_VALUE >> 1;
944 	writel((u32) (wrap_top_dir.val), remapped_regs + mmWRAP_TOP_DIR);
945 
946 	writel((u32) 0x2440, remapped_regs + mmRBBM_CNTL);
947 
948 	/* Set the hardware to 565 colour */
949 	temp32 = readl(remapped_regs + mmDISP_DEBUG2);
950 	temp32 &= 0xff7fffff;
951 	temp32 |= 0x00800000;
952 	writel(temp32, remapped_regs + mmDISP_DEBUG2);
953 
954 	/* Initialise the GPIO lines */
955 	if (gpio) {
956 		writel(gpio->init_data1, remapped_regs + mmGPIO_DATA);
957 		writel(gpio->init_data2, remapped_regs + mmGPIO_DATA2);
958 		writel(gpio->gpio_dir1,  remapped_regs + mmGPIO_CNTL1);
959 		writel(gpio->gpio_oe1,   remapped_regs + mmGPIO_CNTL2);
960 		writel(gpio->gpio_dir2,  remapped_regs + mmGPIO_CNTL3);
961 		writel(gpio->gpio_oe2,   remapped_regs + mmGPIO_CNTL4);
962 	}
963 }
964 
965 
966 struct power_state {
967 	union clk_pin_cntl_u clk_pin_cntl;
968 	union pll_ref_fb_div_u pll_ref_fb_div;
969 	union pll_cntl_u pll_cntl;
970 	union sclk_cntl_u sclk_cntl;
971 	union pclk_cntl_u pclk_cntl;
972 	union pwrmgt_cntl_u pwrmgt_cntl;
973 	int auto_mode;  /* system clock auto changing? */
974 };
975 
976 
977 static struct power_state w100_pwr_state;
978 
979 /* The PLL Fout is determined by (XtalFreq/(M+1)) * ((N_int+1) + (N_fac/8)) */
980 
981 /* 12.5MHz Crystal PLL Table */
982 static struct w100_pll_info xtal_12500000[] = {
983 	/*freq     M   N_int    N_fac  tfgoal  lock_time */
984 	{ 50,      0,   1,       0,     0xe0,        56},  /*  50.00 MHz */
985 	{ 75,      0,   5,       0,     0xde,        37},  /*  75.00 MHz */
986 	{100,      0,   7,       0,     0xe0,        28},  /* 100.00 MHz */
987 	{125,      0,   9,       0,     0xe0,        22},  /* 125.00 MHz */
988 	{150,      0,   11,      0,     0xe0,        17},  /* 150.00 MHz */
989 	{  0,      0,   0,       0,        0,         0},  /* Terminator */
990 };
991 
992 /* 14.318MHz Crystal PLL Table */
993 static struct w100_pll_info xtal_14318000[] = {
994 	/*freq     M   N_int    N_fac  tfgoal  lock_time */
995 	{ 40,      4,   13,      0,     0xe0,        80}, /* tfgoal guessed */
996 	{ 50,      1,   6,       0,     0xe0,	     64}, /*  50.05 MHz */
997 	{ 57,      2,   11,      0,     0xe0,        53}, /* tfgoal guessed */
998 	{ 75,      0,   4,       3,     0xe0,	     43}, /*  75.08 MHz */
999 	{100,      0,   6,       0,     0xe0,        32}, /* 100.10 MHz */
1000 	{  0,      0,   0,       0,        0,         0},
1001 };
1002 
1003 /* 16MHz Crystal PLL Table */
1004 static struct w100_pll_info xtal_16000000[] = {
1005 	/*freq     M   N_int    N_fac  tfgoal  lock_time */
1006 	{ 72,      1,   8,       0,     0xe0,        48}, /* tfgoal guessed */
1007 	{ 80,      1,   9,       0,     0xe0,        13}, /* tfgoal guessed */
1008 	{ 95,      1,   10,      7,     0xe0,        38}, /* tfgoal guessed */
1009 	{ 96,      1,   11,      0,     0xe0,        36}, /* tfgoal guessed */
1010 	{  0,      0,   0,       0,        0,         0},
1011 };
1012 
1013 static struct pll_entries {
1014 	int xtal_freq;
1015 	struct w100_pll_info *pll_table;
1016 } w100_pll_tables[] = {
1017 	{ 12500000, &xtal_12500000[0] },
1018 	{ 14318000, &xtal_14318000[0] },
1019 	{ 16000000, &xtal_16000000[0] },
1020 	{ 0 },
1021 };
1022 
w100_get_xtal_table(unsigned int freq)1023 struct w100_pll_info *w100_get_xtal_table(unsigned int freq)
1024 {
1025 	struct pll_entries *pll_entry = w100_pll_tables;
1026 
1027 	do {
1028 		if (freq == pll_entry->xtal_freq)
1029 			return pll_entry->pll_table;
1030 		pll_entry++;
1031 	} while (pll_entry->xtal_freq);
1032 	return 0;
1033 }
1034 
1035 
w100_get_testcount(unsigned int testclk_sel)1036 static unsigned int w100_get_testcount(unsigned int testclk_sel)
1037 {
1038 	union clk_test_cntl_u clk_test_cntl;
1039 
1040 	udelay(5);
1041 
1042 	/* Select the test clock source and reset */
1043 	clk_test_cntl.f.start_check_freq = 0x0;
1044 	clk_test_cntl.f.testclk_sel = testclk_sel;
1045 	clk_test_cntl.f.tstcount_rst = 0x1; /* set reset */
1046 	writel((u32) (clk_test_cntl.val), remapped_regs + mmCLK_TEST_CNTL);
1047 
1048 	clk_test_cntl.f.tstcount_rst = 0x0; /* clear reset */
1049 	writel((u32) (clk_test_cntl.val), remapped_regs + mmCLK_TEST_CNTL);
1050 
1051 	/* Run clock test */
1052 	clk_test_cntl.f.start_check_freq = 0x1;
1053 	writel((u32) (clk_test_cntl.val), remapped_regs + mmCLK_TEST_CNTL);
1054 
1055 	/* Give the test time to complete */
1056 	udelay(20);
1057 
1058 	/* Return the result */
1059 	clk_test_cntl.val = readl(remapped_regs + mmCLK_TEST_CNTL);
1060 	clk_test_cntl.f.start_check_freq = 0x0;
1061 	writel((u32) (clk_test_cntl.val), remapped_regs + mmCLK_TEST_CNTL);
1062 
1063 	return clk_test_cntl.f.test_count;
1064 }
1065 
1066 
w100_pll_adjust(struct w100_pll_info * pll)1067 static int w100_pll_adjust(struct w100_pll_info *pll)
1068 {
1069 	unsigned int tf80;
1070 	unsigned int tf20;
1071 
1072 	/* Initial Settings */
1073 	w100_pwr_state.pll_cntl.f.pll_pwdn = 0x0;     /* power down */
1074 	w100_pwr_state.pll_cntl.f.pll_reset = 0x0;    /* not reset */
1075 	w100_pwr_state.pll_cntl.f.pll_tcpoff = 0x1;   /* Hi-Z */
1076 	w100_pwr_state.pll_cntl.f.pll_pvg = 0x0;      /* VCO gain = 0 */
1077 	w100_pwr_state.pll_cntl.f.pll_vcofr = 0x0;    /* VCO frequency range control = off */
1078 	w100_pwr_state.pll_cntl.f.pll_ioffset = 0x0;  /* current offset inside VCO = 0 */
1079 	w100_pwr_state.pll_cntl.f.pll_ring_off = 0x0;
1080 
1081 	/* Wai Ming 80 percent of VDD 1.3V gives 1.04V, minimum operating voltage is 1.08V
1082 	 * therefore, commented out the following lines
1083 	 * tf80 meant tf100
1084 	 */
1085 	do {
1086 		/* set VCO input = 0.8 * VDD */
1087 		w100_pwr_state.pll_cntl.f.pll_dactal = 0xd;
1088 		writel((u32) (w100_pwr_state.pll_cntl.val), remapped_regs + mmPLL_CNTL);
1089 
1090 		tf80 = w100_get_testcount(TESTCLK_SRC_PLL);
1091 		if (tf80 >= (pll->tfgoal)) {
1092 			/* set VCO input = 0.2 * VDD */
1093 			w100_pwr_state.pll_cntl.f.pll_dactal = 0x7;
1094 			writel((u32) (w100_pwr_state.pll_cntl.val), remapped_regs + mmPLL_CNTL);
1095 
1096 			tf20 = w100_get_testcount(TESTCLK_SRC_PLL);
1097 			if (tf20 <= (pll->tfgoal))
1098 				return 1;  /* Success */
1099 
1100 			if ((w100_pwr_state.pll_cntl.f.pll_vcofr == 0x0) &&
1101 				((w100_pwr_state.pll_cntl.f.pll_pvg == 0x7) ||
1102 				(w100_pwr_state.pll_cntl.f.pll_ioffset == 0x0))) {
1103 				/* slow VCO config */
1104 				w100_pwr_state.pll_cntl.f.pll_vcofr = 0x1;
1105 				w100_pwr_state.pll_cntl.f.pll_pvg = 0x0;
1106 				w100_pwr_state.pll_cntl.f.pll_ioffset = 0x0;
1107 				continue;
1108 			}
1109 		}
1110 		if ((w100_pwr_state.pll_cntl.f.pll_ioffset) < 0x3) {
1111 			w100_pwr_state.pll_cntl.f.pll_ioffset += 0x1;
1112 		} else if ((w100_pwr_state.pll_cntl.f.pll_pvg) < 0x7) {
1113 			w100_pwr_state.pll_cntl.f.pll_ioffset = 0x0;
1114 			w100_pwr_state.pll_cntl.f.pll_pvg += 0x1;
1115 		} else {
1116 			return 0;  /* Error */
1117 		}
1118 	} while(1);
1119 }
1120 
1121 
1122 /*
1123  * w100_pll_calibration
1124  */
w100_pll_calibration(struct w100_pll_info * pll)1125 static int w100_pll_calibration(struct w100_pll_info *pll)
1126 {
1127 	int status;
1128 
1129 	status = w100_pll_adjust(pll);
1130 
1131 	/* PLL Reset And Lock */
1132 	/* set VCO input = 0.5 * VDD */
1133 	w100_pwr_state.pll_cntl.f.pll_dactal = 0xa;
1134 	writel((u32) (w100_pwr_state.pll_cntl.val), remapped_regs + mmPLL_CNTL);
1135 
1136 	udelay(1);  /* reset time */
1137 
1138 	/* enable charge pump */
1139 	w100_pwr_state.pll_cntl.f.pll_tcpoff = 0x0;  /* normal */
1140 	writel((u32) (w100_pwr_state.pll_cntl.val), remapped_regs + mmPLL_CNTL);
1141 
1142 	/* set VCO input = Hi-Z, disable DAC */
1143 	w100_pwr_state.pll_cntl.f.pll_dactal = 0x0;
1144 	writel((u32) (w100_pwr_state.pll_cntl.val), remapped_regs + mmPLL_CNTL);
1145 
1146 	udelay(400);  /* lock time */
1147 
1148 	/* PLL locked */
1149 
1150 	return status;
1151 }
1152 
1153 
w100_pll_set_clk(struct w100_pll_info * pll)1154 static int w100_pll_set_clk(struct w100_pll_info *pll)
1155 {
1156 	int status;
1157 
1158 	if (w100_pwr_state.auto_mode == 1)  /* auto mode */
1159 	{
1160 		w100_pwr_state.pwrmgt_cntl.f.pwm_fast_noml_hw_en = 0x0;  /* disable fast to normal */
1161 		w100_pwr_state.pwrmgt_cntl.f.pwm_noml_fast_hw_en = 0x0;  /* disable normal to fast */
1162 		writel((u32) (w100_pwr_state.pwrmgt_cntl.val), remapped_regs + mmPWRMGT_CNTL);
1163 	}
1164 
1165 	/* Set system clock source to XTAL whilst adjusting the PLL! */
1166 	w100_pwr_state.sclk_cntl.f.sclk_src_sel = CLK_SRC_XTAL;
1167 	writel((u32) (w100_pwr_state.sclk_cntl.val), remapped_regs + mmSCLK_CNTL);
1168 
1169 	w100_pwr_state.pll_ref_fb_div.f.pll_ref_div = pll->M;
1170 	w100_pwr_state.pll_ref_fb_div.f.pll_fb_div_int = pll->N_int;
1171 	w100_pwr_state.pll_ref_fb_div.f.pll_fb_div_frac = pll->N_fac;
1172 	w100_pwr_state.pll_ref_fb_div.f.pll_lock_time = pll->lock_time;
1173 	writel((u32) (w100_pwr_state.pll_ref_fb_div.val), remapped_regs + mmPLL_REF_FB_DIV);
1174 
1175 	w100_pwr_state.pwrmgt_cntl.f.pwm_mode_req = 0;
1176 	writel((u32) (w100_pwr_state.pwrmgt_cntl.val), remapped_regs + mmPWRMGT_CNTL);
1177 
1178 	status = w100_pll_calibration(pll);
1179 
1180 	if (w100_pwr_state.auto_mode == 1)  /* auto mode */
1181 	{
1182 		w100_pwr_state.pwrmgt_cntl.f.pwm_fast_noml_hw_en = 0x1;  /* reenable fast to normal */
1183 		w100_pwr_state.pwrmgt_cntl.f.pwm_noml_fast_hw_en = 0x1;  /* reenable normal to fast  */
1184 		writel((u32) (w100_pwr_state.pwrmgt_cntl.val), remapped_regs + mmPWRMGT_CNTL);
1185 	}
1186 	return status;
1187 }
1188 
1189 /* freq = target frequency of the PLL */
w100_set_pll_freq(struct w100fb_par * par,unsigned int freq)1190 static int w100_set_pll_freq(struct w100fb_par *par, unsigned int freq)
1191 {
1192 	struct w100_pll_info *pll = par->pll_table;
1193 
1194 	do {
1195 		if (freq == pll->freq) {
1196 			return w100_pll_set_clk(pll);
1197 		}
1198 		pll++;
1199 	} while(pll->freq);
1200 	return 0;
1201 }
1202 
1203 /* Set up an initial state.  Some values/fields set
1204    here will be overwritten. */
w100_pwm_setup(struct w100fb_par * par)1205 static void w100_pwm_setup(struct w100fb_par *par)
1206 {
1207 	w100_pwr_state.clk_pin_cntl.f.osc_en = 0x1;
1208 	w100_pwr_state.clk_pin_cntl.f.osc_gain = 0x1f;
1209 	w100_pwr_state.clk_pin_cntl.f.dont_use_xtalin = 0x0;
1210 	w100_pwr_state.clk_pin_cntl.f.xtalin_pm_en = 0x0;
1211 	w100_pwr_state.clk_pin_cntl.f.xtalin_dbl_en = par->mach->xtal_dbl ? 1 : 0;
1212 	w100_pwr_state.clk_pin_cntl.f.cg_debug = 0x0;
1213 	writel((u32) (w100_pwr_state.clk_pin_cntl.val), remapped_regs + mmCLK_PIN_CNTL);
1214 
1215 	w100_pwr_state.sclk_cntl.f.sclk_src_sel = CLK_SRC_XTAL;
1216 	w100_pwr_state.sclk_cntl.f.sclk_post_div_fast = 0x0;  /* Pfast = 1 */
1217 	w100_pwr_state.sclk_cntl.f.sclk_clkon_hys = 0x3;
1218 	w100_pwr_state.sclk_cntl.f.sclk_post_div_slow = 0x0;  /* Pslow = 1 */
1219 	w100_pwr_state.sclk_cntl.f.disp_cg_ok2switch_en = 0x0;
1220 	w100_pwr_state.sclk_cntl.f.sclk_force_reg = 0x0;    /* Dynamic */
1221 	w100_pwr_state.sclk_cntl.f.sclk_force_disp = 0x0;   /* Dynamic */
1222 	w100_pwr_state.sclk_cntl.f.sclk_force_mc = 0x0;     /* Dynamic */
1223 	w100_pwr_state.sclk_cntl.f.sclk_force_extmc = 0x0;  /* Dynamic */
1224 	w100_pwr_state.sclk_cntl.f.sclk_force_cp = 0x0;     /* Dynamic */
1225 	w100_pwr_state.sclk_cntl.f.sclk_force_e2 = 0x0;     /* Dynamic */
1226 	w100_pwr_state.sclk_cntl.f.sclk_force_e3 = 0x0;     /* Dynamic */
1227 	w100_pwr_state.sclk_cntl.f.sclk_force_idct = 0x0;   /* Dynamic */
1228 	w100_pwr_state.sclk_cntl.f.sclk_force_bist = 0x0;   /* Dynamic */
1229 	w100_pwr_state.sclk_cntl.f.busy_extend_cp = 0x0;
1230 	w100_pwr_state.sclk_cntl.f.busy_extend_e2 = 0x0;
1231 	w100_pwr_state.sclk_cntl.f.busy_extend_e3 = 0x0;
1232 	w100_pwr_state.sclk_cntl.f.busy_extend_idct = 0x0;
1233 	writel((u32) (w100_pwr_state.sclk_cntl.val), remapped_regs + mmSCLK_CNTL);
1234 
1235 	w100_pwr_state.pclk_cntl.f.pclk_src_sel = CLK_SRC_XTAL;
1236 	w100_pwr_state.pclk_cntl.f.pclk_post_div = 0x1;    /* P = 2 */
1237 	w100_pwr_state.pclk_cntl.f.pclk_force_disp = 0x0;  /* Dynamic */
1238 	writel((u32) (w100_pwr_state.pclk_cntl.val), remapped_regs + mmPCLK_CNTL);
1239 
1240 	w100_pwr_state.pll_ref_fb_div.f.pll_ref_div = 0x0;     /* M = 1 */
1241 	w100_pwr_state.pll_ref_fb_div.f.pll_fb_div_int = 0x0;  /* N = 1.0 */
1242 	w100_pwr_state.pll_ref_fb_div.f.pll_fb_div_frac = 0x0;
1243 	w100_pwr_state.pll_ref_fb_div.f.pll_reset_time = 0x5;
1244 	w100_pwr_state.pll_ref_fb_div.f.pll_lock_time = 0xff;
1245 	writel((u32) (w100_pwr_state.pll_ref_fb_div.val), remapped_regs + mmPLL_REF_FB_DIV);
1246 
1247 	w100_pwr_state.pll_cntl.f.pll_pwdn = 0x1;
1248 	w100_pwr_state.pll_cntl.f.pll_reset = 0x1;
1249 	w100_pwr_state.pll_cntl.f.pll_pm_en = 0x0;
1250 	w100_pwr_state.pll_cntl.f.pll_mode = 0x0;  /* uses VCO clock */
1251 	w100_pwr_state.pll_cntl.f.pll_refclk_sel = 0x0;
1252 	w100_pwr_state.pll_cntl.f.pll_fbclk_sel = 0x0;
1253 	w100_pwr_state.pll_cntl.f.pll_tcpoff = 0x0;
1254 	w100_pwr_state.pll_cntl.f.pll_pcp = 0x4;
1255 	w100_pwr_state.pll_cntl.f.pll_pvg = 0x0;
1256 	w100_pwr_state.pll_cntl.f.pll_vcofr = 0x0;
1257 	w100_pwr_state.pll_cntl.f.pll_ioffset = 0x0;
1258 	w100_pwr_state.pll_cntl.f.pll_pecc_mode = 0x0;
1259 	w100_pwr_state.pll_cntl.f.pll_pecc_scon = 0x0;
1260 	w100_pwr_state.pll_cntl.f.pll_dactal = 0x0;  /* Hi-Z */
1261 	w100_pwr_state.pll_cntl.f.pll_cp_clip = 0x3;
1262 	w100_pwr_state.pll_cntl.f.pll_conf = 0x2;
1263 	w100_pwr_state.pll_cntl.f.pll_mbctrl = 0x2;
1264 	w100_pwr_state.pll_cntl.f.pll_ring_off = 0x0;
1265 	writel((u32) (w100_pwr_state.pll_cntl.val), remapped_regs + mmPLL_CNTL);
1266 
1267 	w100_pwr_state.pwrmgt_cntl.f.pwm_enable = 0x0;
1268 	w100_pwr_state.pwrmgt_cntl.f.pwm_mode_req = 0x1;  /* normal mode (0, 1, 3) */
1269 	w100_pwr_state.pwrmgt_cntl.f.pwm_wakeup_cond = 0x0;
1270 	w100_pwr_state.pwrmgt_cntl.f.pwm_fast_noml_hw_en = 0x0;
1271 	w100_pwr_state.pwrmgt_cntl.f.pwm_noml_fast_hw_en = 0x0;
1272 	w100_pwr_state.pwrmgt_cntl.f.pwm_fast_noml_cond = 0x1;  /* PM4,ENG */
1273 	w100_pwr_state.pwrmgt_cntl.f.pwm_noml_fast_cond = 0x1;  /* PM4,ENG */
1274 	w100_pwr_state.pwrmgt_cntl.f.pwm_idle_timer = 0xFF;
1275 	w100_pwr_state.pwrmgt_cntl.f.pwm_busy_timer = 0xFF;
1276 	writel((u32) (w100_pwr_state.pwrmgt_cntl.val), remapped_regs + mmPWRMGT_CNTL);
1277 
1278 	w100_pwr_state.auto_mode = 0;  /* manual mode */
1279 }
1280 
1281 
1282 /*
1283  * Setup the w100 clocks for the specified mode
1284  */
w100_init_clocks(struct w100fb_par * par)1285 static void w100_init_clocks(struct w100fb_par *par)
1286 {
1287 	struct w100_mode *mode = par->mode;
1288 
1289 	if (mode->pixclk_src == CLK_SRC_PLL || mode->sysclk_src == CLK_SRC_PLL)
1290 		w100_set_pll_freq(par, (par->fastpll_mode && mode->fast_pll_freq) ? mode->fast_pll_freq : mode->pll_freq);
1291 
1292 	w100_pwr_state.sclk_cntl.f.sclk_src_sel = mode->sysclk_src;
1293 	w100_pwr_state.sclk_cntl.f.sclk_post_div_fast = mode->sysclk_divider;
1294 	w100_pwr_state.sclk_cntl.f.sclk_post_div_slow = mode->sysclk_divider;
1295 	writel((u32) (w100_pwr_state.sclk_cntl.val), remapped_regs + mmSCLK_CNTL);
1296 }
1297 
w100_init_lcd(struct w100fb_par * par)1298 static void w100_init_lcd(struct w100fb_par *par)
1299 {
1300 	u32 temp32;
1301 	struct w100_mode *mode = par->mode;
1302 	struct w100_gen_regs *regs = par->mach->regs;
1303 	union active_h_disp_u active_h_disp;
1304 	union active_v_disp_u active_v_disp;
1305 	union graphic_h_disp_u graphic_h_disp;
1306 	union graphic_v_disp_u graphic_v_disp;
1307 	union crtc_total_u crtc_total;
1308 
1309 	/* w3200 doesn't like undefined bits being set so zero register values first */
1310 
1311 	active_h_disp.val = 0;
1312 	active_h_disp.f.active_h_start=mode->left_margin;
1313 	active_h_disp.f.active_h_end=mode->left_margin + mode->xres;
1314 	writel(active_h_disp.val, remapped_regs + mmACTIVE_H_DISP);
1315 
1316 	active_v_disp.val = 0;
1317 	active_v_disp.f.active_v_start=mode->upper_margin;
1318 	active_v_disp.f.active_v_end=mode->upper_margin + mode->yres;
1319 	writel(active_v_disp.val, remapped_regs + mmACTIVE_V_DISP);
1320 
1321 	graphic_h_disp.val = 0;
1322 	graphic_h_disp.f.graphic_h_start=mode->left_margin;
1323 	graphic_h_disp.f.graphic_h_end=mode->left_margin + mode->xres;
1324 	writel(graphic_h_disp.val, remapped_regs + mmGRAPHIC_H_DISP);
1325 
1326 	graphic_v_disp.val = 0;
1327 	graphic_v_disp.f.graphic_v_start=mode->upper_margin;
1328 	graphic_v_disp.f.graphic_v_end=mode->upper_margin + mode->yres;
1329 	writel(graphic_v_disp.val, remapped_regs + mmGRAPHIC_V_DISP);
1330 
1331 	crtc_total.val = 0;
1332 	crtc_total.f.crtc_h_total=mode->left_margin  + mode->xres + mode->right_margin;
1333 	crtc_total.f.crtc_v_total=mode->upper_margin + mode->yres + mode->lower_margin;
1334 	writel(crtc_total.val, remapped_regs + mmCRTC_TOTAL);
1335 
1336 	writel(mode->crtc_ss, remapped_regs + mmCRTC_SS);
1337 	writel(mode->crtc_ls, remapped_regs + mmCRTC_LS);
1338 	writel(mode->crtc_gs, remapped_regs + mmCRTC_GS);
1339 	writel(mode->crtc_vpos_gs, remapped_regs + mmCRTC_VPOS_GS);
1340 	writel(mode->crtc_rev, remapped_regs + mmCRTC_REV);
1341 	writel(mode->crtc_dclk, remapped_regs + mmCRTC_DCLK);
1342 	writel(mode->crtc_gclk, remapped_regs + mmCRTC_GCLK);
1343 	writel(mode->crtc_goe, remapped_regs + mmCRTC_GOE);
1344 	writel(mode->crtc_ps1_active, remapped_regs + mmCRTC_PS1_ACTIVE);
1345 
1346 	writel(regs->lcd_format, remapped_regs + mmLCD_FORMAT);
1347 	writel(regs->lcdd_cntl1, remapped_regs + mmLCDD_CNTL1);
1348 	writel(regs->lcdd_cntl2, remapped_regs + mmLCDD_CNTL2);
1349 	writel(regs->genlcd_cntl1, remapped_regs + mmGENLCD_CNTL1);
1350 	writel(regs->genlcd_cntl2, remapped_regs + mmGENLCD_CNTL2);
1351 	writel(regs->genlcd_cntl3, remapped_regs + mmGENLCD_CNTL3);
1352 
1353 	writel(0x00000000, remapped_regs + mmCRTC_FRAME);
1354 	writel(0x00000000, remapped_regs + mmCRTC_FRAME_VPOS);
1355 	writel(0x00000000, remapped_regs + mmCRTC_DEFAULT_COUNT);
1356 	writel(0x0000FF00, remapped_regs + mmLCD_BACKGROUND_COLOR);
1357 
1358 	/* Hack for overlay in ext memory */
1359 	temp32 = readl(remapped_regs + mmDISP_DEBUG2);
1360 	temp32 |= 0xc0000000;
1361 	writel(temp32, remapped_regs + mmDISP_DEBUG2);
1362 }
1363 
1364 
w100_setup_memory(struct w100fb_par * par)1365 static void w100_setup_memory(struct w100fb_par *par)
1366 {
1367 	union mc_ext_mem_location_u extmem_location;
1368 	union mc_fb_location_u intmem_location;
1369 	struct w100_mem_info *mem = par->mach->mem;
1370 	struct w100_bm_mem_info *bm_mem = par->mach->bm_mem;
1371 
1372 	if (!par->extmem_active) {
1373 		w100_suspend(W100_SUSPEND_EXTMEM);
1374 
1375 		/* Map Internal Memory at FB Base */
1376 		intmem_location.f.mc_fb_start = W100_FB_BASE >> 8;
1377 		intmem_location.f.mc_fb_top = (W100_FB_BASE+MEM_INT_SIZE) >> 8;
1378 		writel((u32) (intmem_location.val), remapped_regs + mmMC_FB_LOCATION);
1379 
1380 		/* Unmap External Memory - value is *probably* irrelevant but may have meaning
1381 		   to acceleration libraries */
1382 		extmem_location.f.mc_ext_mem_start = MEM_EXT_BASE_VALUE >> 8;
1383 		extmem_location.f.mc_ext_mem_top = (MEM_EXT_BASE_VALUE-1) >> 8;
1384 		writel((u32) (extmem_location.val), remapped_regs + mmMC_EXT_MEM_LOCATION);
1385 	} else {
1386 		/* Map Internal Memory to its default location */
1387 		intmem_location.f.mc_fb_start = MEM_INT_BASE_VALUE >> 8;
1388 		intmem_location.f.mc_fb_top = (MEM_INT_BASE_VALUE+MEM_INT_SIZE) >> 8;
1389 		writel((u32) (intmem_location.val), remapped_regs + mmMC_FB_LOCATION);
1390 
1391 		/* Map External Memory at FB Base */
1392 		extmem_location.f.mc_ext_mem_start = W100_FB_BASE >> 8;
1393 		extmem_location.f.mc_ext_mem_top = (W100_FB_BASE+par->mach->mem->size) >> 8;
1394 		writel((u32) (extmem_location.val), remapped_regs + mmMC_EXT_MEM_LOCATION);
1395 
1396 		writel(0x00007800, remapped_regs + mmMC_BIST_CTRL);
1397 		writel(mem->ext_cntl, remapped_regs + mmMEM_EXT_CNTL);
1398 		writel(0x00200021, remapped_regs + mmMEM_SDRAM_MODE_REG);
1399 		udelay(100);
1400 		writel(0x80200021, remapped_regs + mmMEM_SDRAM_MODE_REG);
1401 		udelay(100);
1402 		writel(mem->sdram_mode_reg, remapped_regs + mmMEM_SDRAM_MODE_REG);
1403 		udelay(100);
1404 		writel(mem->ext_timing_cntl, remapped_regs + mmMEM_EXT_TIMING_CNTL);
1405 		writel(mem->io_cntl, remapped_regs + mmMEM_IO_CNTL);
1406 		if (bm_mem) {
1407 			writel(bm_mem->ext_mem_bw, remapped_regs + mmBM_EXT_MEM_BANDWIDTH);
1408 			writel(bm_mem->offset, remapped_regs + mmBM_OFFSET);
1409 			writel(bm_mem->ext_timing_ctl, remapped_regs + mmBM_MEM_EXT_TIMING_CNTL);
1410 			writel(bm_mem->ext_cntl, remapped_regs + mmBM_MEM_EXT_CNTL);
1411 			writel(bm_mem->mode_reg, remapped_regs + mmBM_MEM_MODE_REG);
1412 			writel(bm_mem->io_cntl, remapped_regs + mmBM_MEM_IO_CNTL);
1413 			writel(bm_mem->config, remapped_regs + mmBM_CONFIG);
1414 		}
1415 	}
1416 }
1417 
w100_set_dispregs(struct w100fb_par * par)1418 static void w100_set_dispregs(struct w100fb_par *par)
1419 {
1420 	unsigned long rot=0, divider, offset=0;
1421 	union graphic_ctrl_u graphic_ctrl;
1422 
1423 	/* See if the mode has been rotated */
1424 	if (par->xres == par->mode->xres) {
1425 		if (par->flip) {
1426 			rot=3; /* 180 degree */
1427 			offset=(par->xres * par->yres) - 1;
1428 		} /* else 0 degree */
1429 		divider = par->mode->pixclk_divider;
1430 	} else {
1431 		if (par->flip) {
1432 			rot=2; /* 270 degree */
1433 			offset=par->xres - 1;
1434 		} else {
1435 			rot=1; /* 90 degree */
1436 			offset=par->xres * (par->yres - 1);
1437 		}
1438 		divider = par->mode->pixclk_divider_rotated;
1439 	}
1440 
1441 	graphic_ctrl.val = 0; /* w32xx doesn't like undefined bits */
1442 	switch (par->chip_id) {
1443 		case CHIP_ID_W100:
1444 			graphic_ctrl.f_w100.color_depth=6;
1445 			graphic_ctrl.f_w100.en_crtc=1;
1446 			graphic_ctrl.f_w100.en_graphic_req=1;
1447 			graphic_ctrl.f_w100.en_graphic_crtc=1;
1448 			graphic_ctrl.f_w100.lcd_pclk_on=1;
1449 			graphic_ctrl.f_w100.lcd_sclk_on=1;
1450 			graphic_ctrl.f_w100.low_power_on=0;
1451 			graphic_ctrl.f_w100.req_freq=0;
1452 			graphic_ctrl.f_w100.portrait_mode=rot;
1453 
1454 			/* Zaurus needs this */
1455 			switch(par->xres) {
1456 				case 240:
1457 				case 320:
1458 				default:
1459 					graphic_ctrl.f_w100.total_req_graphic=0xa0;
1460 					break;
1461 				case 480:
1462 				case 640:
1463 					switch(rot) {
1464 						case 0:  /* 0 */
1465 						case 3:  /* 180 */
1466 							graphic_ctrl.f_w100.low_power_on=1;
1467 							graphic_ctrl.f_w100.req_freq=5;
1468 						break;
1469 						case 1:  /* 90 */
1470 						case 2:  /* 270 */
1471 							graphic_ctrl.f_w100.req_freq=4;
1472 							break;
1473 						default:
1474 							break;
1475 					}
1476 					graphic_ctrl.f_w100.total_req_graphic=0xf0;
1477 					break;
1478 			}
1479 			break;
1480 		case CHIP_ID_W3200:
1481 		case CHIP_ID_W3220:
1482 			graphic_ctrl.f_w32xx.color_depth=6;
1483 			graphic_ctrl.f_w32xx.en_crtc=1;
1484 			graphic_ctrl.f_w32xx.en_graphic_req=1;
1485 			graphic_ctrl.f_w32xx.en_graphic_crtc=1;
1486 			graphic_ctrl.f_w32xx.lcd_pclk_on=1;
1487 			graphic_ctrl.f_w32xx.lcd_sclk_on=1;
1488 			graphic_ctrl.f_w32xx.low_power_on=0;
1489 			graphic_ctrl.f_w32xx.req_freq=0;
1490 			graphic_ctrl.f_w32xx.total_req_graphic=par->mode->xres >> 1; /* panel xres, not mode */
1491 			graphic_ctrl.f_w32xx.portrait_mode=rot;
1492 			break;
1493 	}
1494 
1495 	/* Set the pixel clock source and divider */
1496 	w100_pwr_state.pclk_cntl.f.pclk_src_sel = par->mode->pixclk_src;
1497 	w100_pwr_state.pclk_cntl.f.pclk_post_div = divider;
1498 	writel((u32) (w100_pwr_state.pclk_cntl.val), remapped_regs + mmPCLK_CNTL);
1499 
1500 	writel(graphic_ctrl.val, remapped_regs + mmGRAPHIC_CTRL);
1501 	writel(W100_FB_BASE + ((offset * BITS_PER_PIXEL/8)&~0x03UL), remapped_regs + mmGRAPHIC_OFFSET);
1502 	writel((par->xres*BITS_PER_PIXEL/8), remapped_regs + mmGRAPHIC_PITCH);
1503 }
1504 
1505 
1506 /*
1507  * Work out how long the sync pulse lasts
1508  * Value is 1/(time in seconds)
1509  */
calc_hsync(struct w100fb_par * par)1510 static void calc_hsync(struct w100fb_par *par)
1511 {
1512 	unsigned long hsync;
1513 	struct w100_mode *mode = par->mode;
1514 	union crtc_ss_u crtc_ss;
1515 
1516 	if (mode->pixclk_src == CLK_SRC_XTAL)
1517 		hsync=par->mach->xtal_freq;
1518 	else
1519 		hsync=((par->fastpll_mode && mode->fast_pll_freq) ? mode->fast_pll_freq : mode->pll_freq)*100000;
1520 
1521 	hsync /= (w100_pwr_state.pclk_cntl.f.pclk_post_div + 1);
1522 
1523 	crtc_ss.val = readl(remapped_regs + mmCRTC_SS);
1524 	if (crtc_ss.val)
1525 		par->hsync_len = hsync / (crtc_ss.f.ss_end-crtc_ss.f.ss_start);
1526 	else
1527 		par->hsync_len = 0;
1528 }
1529 
w100_suspend(u32 mode)1530 static void w100_suspend(u32 mode)
1531 {
1532 	u32 val;
1533 
1534 	writel(0x7FFF8000, remapped_regs + mmMC_EXT_MEM_LOCATION);
1535 	writel(0x00FF0000, remapped_regs + mmMC_PERF_MON_CNTL);
1536 
1537 	val = readl(remapped_regs + mmMEM_EXT_TIMING_CNTL);
1538 	val &= ~(0x00100000);  /* bit20=0 */
1539 	val |= 0xFF000000;     /* bit31:24=0xff */
1540 	writel(val, remapped_regs + mmMEM_EXT_TIMING_CNTL);
1541 
1542 	val = readl(remapped_regs + mmMEM_EXT_CNTL);
1543 	val &= ~(0x00040000);  /* bit18=0 */
1544 	val |= 0x00080000;     /* bit19=1 */
1545 	writel(val, remapped_regs + mmMEM_EXT_CNTL);
1546 
1547 	udelay(1);  /* wait 1us */
1548 
1549 	if (mode == W100_SUSPEND_EXTMEM) {
1550 		/* CKE: Tri-State */
1551 		val = readl(remapped_regs + mmMEM_EXT_CNTL);
1552 		val |= 0x40000000;  /* bit30=1 */
1553 		writel(val, remapped_regs + mmMEM_EXT_CNTL);
1554 
1555 		/* CLK: Stop */
1556 		val = readl(remapped_regs + mmMEM_EXT_CNTL);
1557 		val &= ~(0x00000001);  /* bit0=0 */
1558 		writel(val, remapped_regs + mmMEM_EXT_CNTL);
1559 	} else {
1560 		writel(0x00000000, remapped_regs + mmSCLK_CNTL);
1561 		writel(0x000000BF, remapped_regs + mmCLK_PIN_CNTL);
1562 		writel(0x00000015, remapped_regs + mmPWRMGT_CNTL);
1563 
1564 		udelay(5);
1565 
1566 		val = readl(remapped_regs + mmPLL_CNTL);
1567 		val |= 0x00000004;  /* bit2=1 */
1568 		writel(val, remapped_regs + mmPLL_CNTL);
1569 
1570 		writel(0x00000000, remapped_regs + mmLCDD_CNTL1);
1571 		writel(0x00000000, remapped_regs + mmLCDD_CNTL2);
1572 		writel(0x00000000, remapped_regs + mmGENLCD_CNTL1);
1573 		writel(0x00000000, remapped_regs + mmGENLCD_CNTL2);
1574 		writel(0x00000000, remapped_regs + mmGENLCD_CNTL3);
1575 
1576 		val = readl(remapped_regs + mmMEM_EXT_CNTL);
1577 		val |= 0xF0000000;
1578 		val &= ~(0x00000001);
1579 		writel(val, remapped_regs + mmMEM_EXT_CNTL);
1580 
1581 		writel(0x0000001d, remapped_regs + mmPWRMGT_CNTL);
1582 	}
1583 }
1584 
w100_vsync(void)1585 static void w100_vsync(void)
1586 {
1587 	u32 tmp;
1588 	int timeout = 30000;  /* VSync timeout = 30[ms] > 16.8[ms] */
1589 
1590 	tmp = readl(remapped_regs + mmACTIVE_V_DISP);
1591 
1592 	/* set vline pos  */
1593 	writel((tmp >> 16) & 0x3ff, remapped_regs + mmDISP_INT_CNTL);
1594 
1595 	/* disable vline irq */
1596 	tmp = readl(remapped_regs + mmGEN_INT_CNTL);
1597 
1598 	tmp &= ~0x00000002;
1599 	writel(tmp, remapped_regs + mmGEN_INT_CNTL);
1600 
1601 	/* clear vline irq status */
1602 	writel(0x00000002, remapped_regs + mmGEN_INT_STATUS);
1603 
1604 	/* enable vline irq */
1605 	writel((tmp | 0x00000002), remapped_regs + mmGEN_INT_CNTL);
1606 
1607 	/* clear vline irq status */
1608 	writel(0x00000002, remapped_regs + mmGEN_INT_STATUS);
1609 
1610 	while(timeout > 0) {
1611 		if (readl(remapped_regs + mmGEN_INT_STATUS) & 0x00000002)
1612 			break;
1613 		udelay(1);
1614 		timeout--;
1615 	}
1616 
1617 	/* disable vline irq */
1618 	writel(tmp, remapped_regs + mmGEN_INT_CNTL);
1619 
1620 	/* clear vline irq status */
1621 	writel(0x00000002, remapped_regs + mmGEN_INT_STATUS);
1622 }
1623 
1624 static struct platform_driver w100fb_driver = {
1625 	.probe		= w100fb_probe,
1626 	.remove		= w100fb_remove,
1627 	.suspend	= w100fb_suspend,
1628 	.resume		= w100fb_resume,
1629 	.driver		= {
1630 		.name	= "w100fb",
1631 	},
1632 };
1633 
1634 module_platform_driver(w100fb_driver);
1635 
1636 MODULE_DESCRIPTION("ATI Imageon w100 framebuffer driver");
1637 MODULE_LICENSE("GPL");
1638