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