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