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