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