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