86835ee4102716c130713efd9544c78dbb206ebc
[firefly-linux-kernel-4.4.55.git] / drivers / video / via / viafbdev.c
1 /*
2  * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
3  * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
4
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public
7  * License as published by the Free Software Foundation;
8  * either version 2, or (at your option) any later version.
9
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
12  * the implied warranty of MERCHANTABILITY or FITNESS FOR
13  * A PARTICULAR PURPOSE.See the GNU General Public License
14  * for more details.
15
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc.,
19  * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20  */
21
22 #include <linux/module.h>
23 #define _MASTER_FILE
24
25 #include "global.h"
26
27 static int MAX_CURS = 32;
28 static struct fb_var_screeninfo default_var;
29 static char *viafb_name = "Via";
30 static u32 pseudo_pal[17];
31
32 /* video mode */
33 static char *viafb_mode = "640x480";
34 static char *viafb_mode1 = "640x480";
35
36 /* Added for specifying active devices.*/
37 char *viafb_active_dev = "";
38
39 /* Added for specifying video on devices.*/
40 char *viafb_video_dev = "";
41
42 /*Added for specify lcd output port*/
43 char *viafb_lcd_port = "";
44 char *viafb_dvi_port = "";
45
46 static void viafb_set_device(struct device_t active_dev);
47 static int apply_device_setting(struct viafb_ioctl_setting setting_info,
48                          struct fb_info *info);
49 static void apply_second_mode_setting(struct fb_var_screeninfo
50         *sec_var);
51 static void retrieve_device_setting(struct viafb_ioctl_setting
52         *setting_info);
53 static void viafb_set_video_device(u32 video_dev_info);
54 static void viafb_get_video_device(u32 *video_dev_info);
55
56 static struct fb_ops viafb_ops;
57
58
59 static void viafb_update_fix(struct fb_info *info)
60 {
61         u32 bpp = info->var.bits_per_pixel;
62
63         info->fix.visual =
64                 bpp == 8 ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR;
65         info->fix.line_length =
66                 ((info->var.xres_virtual + 7) & ~7) * bpp / 8;
67 }
68
69 static void viafb_setup_fixinfo(struct fb_fix_screeninfo *fix,
70         struct viafb_par *viaparinfo)
71 {
72         memset(fix, 0, sizeof(struct fb_fix_screeninfo));
73         strcpy(fix->id, viafb_name);
74
75         fix->smem_start = viaparinfo->fbmem;
76         fix->smem_len = viaparinfo->fbmem_free;
77         fix->mmio_start = viaparinfo->mmio_base;
78         fix->mmio_len = viaparinfo->mmio_len;
79
80         fix->type = FB_TYPE_PACKED_PIXELS;
81         fix->type_aux = 0;
82
83         fix->xpanstep = fix->ywrapstep = 0;
84         fix->ypanstep = 1;
85
86         /* Just tell the accel name */
87         viafbinfo->fix.accel = FB_ACCEL_VIA_UNICHROME;
88 }
89 static int viafb_open(struct fb_info *info, int user)
90 {
91         DEBUG_MSG(KERN_INFO "viafb_open!\n");
92         return 0;
93 }
94
95 static int viafb_release(struct fb_info *info, int user)
96 {
97         DEBUG_MSG(KERN_INFO "viafb_release!\n");
98         return 0;
99 }
100
101 static int viafb_check_var(struct fb_var_screeninfo *var,
102         struct fb_info *info)
103 {
104         int vmode_index, htotal, vtotal;
105         struct viafb_par *ppar;
106         u32 long_refresh;
107         struct viafb_par *p_viafb_par;
108         ppar = info->par;
109
110
111         DEBUG_MSG(KERN_INFO "viafb_check_var!\n");
112         /* Sanity check */
113         /* HW neither support interlacte nor double-scaned mode */
114         if (var->vmode & FB_VMODE_INTERLACED || var->vmode & FB_VMODE_DOUBLE)
115                 return -EINVAL;
116
117         vmode_index = viafb_get_mode_index(var->xres, var->yres);
118         if (vmode_index == VIA_RES_INVALID) {
119                 DEBUG_MSG(KERN_INFO
120                           "viafb: Mode %dx%dx%d not supported!!\n",
121                           var->xres, var->yres, var->bits_per_pixel);
122                 return -EINVAL;
123         }
124
125         if (24 == var->bits_per_pixel)
126                 var->bits_per_pixel = 32;
127
128         if (var->bits_per_pixel != 8 && var->bits_per_pixel != 16 &&
129                 var->bits_per_pixel != 32)
130                 return -EINVAL;
131
132         if ((var->xres_virtual * (var->bits_per_pixel >> 3)) & 0x1F)
133                 /*32 pixel alignment */
134                 var->xres_virtual = (var->xres_virtual + 31) & ~31;
135         if (var->xres_virtual * var->yres_virtual * var->bits_per_pixel / 8 >
136                 ppar->memsize)
137                 return -EINVAL;
138
139         /* Based on var passed in to calculate the refresh,
140          * because our driver use some modes special.
141          */
142         htotal = var->xres + var->left_margin +
143         var->right_margin + var->hsync_len;
144         vtotal = var->yres + var->upper_margin +
145                 var->lower_margin + var->vsync_len;
146         long_refresh = 1000000000UL / var->pixclock * 1000;
147         long_refresh /= (htotal * vtotal);
148
149         viafb_refresh = viafb_get_refresh(var->xres, var->yres, long_refresh);
150
151         /* Adjust var according to our driver's own table */
152         viafb_fill_var_timing_info(var, viafb_refresh, vmode_index);
153
154         /* This is indeed a patch for VT3353 */
155         if (!info->par)
156                 return -1;
157         p_viafb_par = (struct viafb_par *)info->par;
158         if (p_viafb_par->chip_info->gfx_chip_name == UNICHROME_VX800)
159                 var->accel_flags = 0;
160
161         return 0;
162 }
163
164 static int viafb_set_par(struct fb_info *info)
165 {
166         int vmode_index;
167         int vmode_index1 = 0;
168         DEBUG_MSG(KERN_INFO "viafb_set_par!\n");
169
170         viafb_update_device_setting(info->var.xres, info->var.yres,
171                               info->var.bits_per_pixel, viafb_refresh, 0);
172
173         vmode_index = viafb_get_mode_index(info->var.xres, info->var.yres);
174
175         if (viafb_SAMM_ON == 1) {
176                 DEBUG_MSG(KERN_INFO
177                 "viafb_second_xres = %d, viafb_second_yres = %d, bpp = %d\n",
178                           viafb_second_xres, viafb_second_yres, viafb_bpp1);
179                 vmode_index1 = viafb_get_mode_index(viafb_second_xres,
180                         viafb_second_yres);
181                 DEBUG_MSG(KERN_INFO "->viafb_SAMM_ON: index=%d\n",
182                         vmode_index1);
183
184                 viafb_update_device_setting(viafb_second_xres,
185                         viafb_second_yres, viafb_bpp1, viafb_refresh1, 1);
186         }
187
188         if (vmode_index != VIA_RES_INVALID) {
189                 viafb_setmode(vmode_index, info->var.xres, info->var.yres,
190                         info->var.bits_per_pixel, vmode_index1,
191                         viafb_second_xres, viafb_second_yres, viafb_bpp1);
192
193                 /*We should set memory offset according virtual_x */
194                 /*Fix me:put this function into viafb_setmode */
195                 viafb_memory_pitch_patch(info);
196                 viafb_update_fix(info);
197                 viafb_bpp = info->var.bits_per_pixel;
198                 /* Update viafb_accel, it is necessary to our 2D accelerate */
199                 viafb_accel = info->var.accel_flags;
200
201                 if (viafb_accel)
202                         viafb_set_2d_color_depth(info->var.bits_per_pixel);
203         }
204
205         return 0;
206 }
207
208 /* Set one color register */
209 static int viafb_setcolreg(unsigned regno, unsigned red, unsigned green,
210 unsigned blue, unsigned transp, struct fb_info *info)
211 {
212         u8 sr1a, sr1b, cr67, cr6a, rev = 0, shift = 10;
213         unsigned cmap_entries = (info->var.bits_per_pixel == 8) ? 256 : 16;
214         DEBUG_MSG(KERN_INFO "viafb_setcolreg!\n");
215         if (regno >= cmap_entries)
216                 return 1;
217         if (UNICHROME_CLE266 == viaparinfo->chip_info->gfx_chip_name) {
218                 /*
219                  * Read PCI bus 0,dev 0,function 0,index 0xF6 to get chip rev.
220                  */
221                 outl(0x80000000 | (0xf6 & ~3), (unsigned long)0xCF8);
222                 rev = (inl((unsigned long)0xCFC) >> ((0xf6 & 3) * 8)) & 0xff;
223         }
224         switch (info->var.bits_per_pixel) {
225         case 8:
226                 outb(0x1A, 0x3C4);
227                 sr1a = inb(0x3C5);
228                 outb(0x1B, 0x3C4);
229                 sr1b = inb(0x3C5);
230                 outb(0x67, 0x3D4);
231                 cr67 = inb(0x3D5);
232                 outb(0x6A, 0x3D4);
233                 cr6a = inb(0x3D5);
234
235                 /* Map the 3C6/7/8/9 to the IGA2 */
236                 outb(0x1A, 0x3C4);
237                 outb(sr1a | 0x01, 0x3C5);
238                 /* Second Display Engine colck always on */
239                 outb(0x1B, 0x3C4);
240                 outb(sr1b | 0x80, 0x3C5);
241                 /* Second Display Color Depth 8 */
242                 outb(0x67, 0x3D4);
243                 outb(cr67 & 0x3F, 0x3D5);
244                 outb(0x6A, 0x3D4);
245                 /* Second Display Channel Reset CR6A[6]) */
246                 outb(cr6a & 0xBF, 0x3D5);
247                 /* Second Display Channel Enable CR6A[7] */
248                 outb(cr6a | 0x80, 0x3D5);
249                 /* Second Display Channel stop reset) */
250                 outb(cr6a | 0x40, 0x3D5);
251
252                 /* Bit mask of palette */
253                 outb(0xFF, 0x3c6);
254                 /* Write one register of IGA2 */
255                 outb(regno, 0x3C8);
256                 if (UNICHROME_CLE266 == viaparinfo->chip_info->gfx_chip_name &&
257                         rev >= 15) {
258                         shift = 8;
259                         viafb_write_reg_mask(CR6A, VIACR, BIT5, BIT5);
260                         viafb_write_reg_mask(SR15, VIASR, BIT7, BIT7);
261                 } else {
262                         shift = 10;
263                         viafb_write_reg_mask(CR6A, VIACR, 0, BIT5);
264                         viafb_write_reg_mask(SR15, VIASR, 0, BIT7);
265                 }
266                 outb(red >> shift, 0x3C9);
267                 outb(green >> shift, 0x3C9);
268                 outb(blue >> shift, 0x3C9);
269
270                 /* Map the 3C6/7/8/9 to the IGA1 */
271                 outb(0x1A, 0x3C4);
272                 outb(sr1a & 0xFE, 0x3C5);
273                 /* Bit mask of palette */
274                 outb(0xFF, 0x3c6);
275                 /* Write one register of IGA1 */
276                 outb(regno, 0x3C8);
277                 outb(red >> shift, 0x3C9);
278                 outb(green >> shift, 0x3C9);
279                 outb(blue >> shift, 0x3C9);
280
281                 outb(0x1A, 0x3C4);
282                 outb(sr1a, 0x3C5);
283                 outb(0x1B, 0x3C4);
284                 outb(sr1b, 0x3C5);
285                 outb(0x67, 0x3D4);
286                 outb(cr67, 0x3D5);
287                 outb(0x6A, 0x3D4);
288                 outb(cr6a, 0x3D5);
289                 break;
290         case 16:
291                 ((u32 *) info->pseudo_palette)[regno] = (red & 0xF800) |
292                     ((green & 0xFC00) >> 5) | ((blue & 0xF800) >> 11);
293                 break;
294         case 32:
295                 ((u32 *) info->pseudo_palette)[regno] =
296                     ((transp & 0xFF00) << 16) |
297                     ((red & 0xFF00) << 8) |
298                     ((green & 0xFF00)) | ((blue & 0xFF00) >> 8);
299                 break;
300         }
301
302         return 0;
303
304 }
305
306 /*CALLED BY: fb_set_cmap */
307 /*           fb_set_var, pass 256 colors */
308 /*CALLED BY: fb_set_cmap */
309 /*           fbcon_set_palette, pass 16 colors */
310 static int viafb_setcmap(struct fb_cmap *cmap, struct fb_info *info)
311 {
312         u32 len = cmap->len;
313         u32 i;
314         u16 *pred = cmap->red;
315         u16 *pgreen = cmap->green;
316         u16 *pblue = cmap->blue;
317         u16 *ptransp = cmap->transp;
318         u8 sr1a, sr1b, cr67, cr6a, rev = 0, shift = 10;
319         if (len > 256)
320                 return 1;
321         if (UNICHROME_CLE266 == viaparinfo->chip_info->gfx_chip_name) {
322                 /*
323                  * Read PCI bus 0, dev 0, function 0, index 0xF6 to get chip
324                  * rev.
325                  */
326                 outl(0x80000000 | (0xf6 & ~3), (unsigned long)0xCF8);
327                 rev = (inl((unsigned long)0xCFC) >> ((0xf6 & 3) * 8)) & 0xff;
328         }
329         switch (info->var.bits_per_pixel) {
330         case 8:
331                 outb(0x1A, 0x3C4);
332                 sr1a = inb(0x3C5);
333                 outb(0x1B, 0x3C4);
334                 sr1b = inb(0x3C5);
335                 outb(0x67, 0x3D4);
336                 cr67 = inb(0x3D5);
337                 outb(0x6A, 0x3D4);
338                 cr6a = inb(0x3D5);
339                 /* Map the 3C6/7/8/9 to the IGA2 */
340                 outb(0x1A, 0x3C4);
341                 outb(sr1a | 0x01, 0x3C5);
342                 outb(0x1B, 0x3C4);
343                 /* Second Display Engine colck always on */
344                 outb(sr1b | 0x80, 0x3C5);
345                 outb(0x67, 0x3D4);
346                 /* Second Display Color Depth 8 */
347                 outb(cr67 & 0x3F, 0x3D5);
348                 outb(0x6A, 0x3D4);
349                 /* Second Display Channel Reset CR6A[6]) */
350                 outb(cr6a & 0xBF, 0x3D5);
351                 /* Second Display Channel Enable CR6A[7] */
352                 outb(cr6a | 0x80, 0x3D5);
353                 /* Second Display Channel stop reset) */
354                 outb(cr6a | 0xC0, 0x3D5);
355
356                 /* Bit mask of palette */
357                 outb(0xFF, 0x3c6);
358                 outb(0x00, 0x3C8);
359                 if (UNICHROME_CLE266 == viaparinfo->chip_info->gfx_chip_name &&
360                         rev >= 15) {
361                         shift = 8;
362                         viafb_write_reg_mask(CR6A, VIACR, BIT5, BIT5);
363                         viafb_write_reg_mask(SR15, VIASR, BIT7, BIT7);
364                 } else {
365                         shift = 10;
366                         viafb_write_reg_mask(CR6A, VIACR, 0, BIT5);
367                         viafb_write_reg_mask(SR15, VIASR, 0, BIT7);
368                 }
369                 for (i = 0; i < len; i++) {
370                         outb((*(pred + i)) >> shift, 0x3C9);
371                         outb((*(pgreen + i)) >> shift, 0x3C9);
372                         outb((*(pblue + i)) >> shift, 0x3C9);
373                 }
374
375                 outb(0x1A, 0x3C4);
376                 /* Map the 3C6/7/8/9 to the IGA1 */
377                 outb(sr1a & 0xFE, 0x3C5);
378                 /* Bit mask of palette */
379                 outb(0xFF, 0x3c6);
380                 outb(0x00, 0x3C8);
381                 for (i = 0; i < len; i++) {
382                         outb((*(pred + i)) >> shift, 0x3C9);
383                         outb((*(pgreen + i)) >> shift, 0x3C9);
384                         outb((*(pblue + i)) >> shift, 0x3C9);
385                 }
386
387                 outb(0x1A, 0x3C4);
388                 outb(sr1a, 0x3C5);
389                 outb(0x1B, 0x3C4);
390                 outb(sr1b, 0x3C5);
391                 outb(0x67, 0x3D4);
392                 outb(cr67, 0x3D5);
393                 outb(0x6A, 0x3D4);
394                 outb(cr6a, 0x3D5);
395                 break;
396         case 16:
397                 if (len > 17)
398                         return 0;       /* Because static u32 pseudo_pal[17]; */
399                 for (i = 0; i < len; i++)
400                         ((u32 *) info->pseudo_palette)[i] =
401                             (*(pred + i) & 0xF800) |
402                             ((*(pgreen + i) & 0xFC00) >> 5) |
403                             ((*(pblue + i) & 0xF800) >> 11);
404                 break;
405         case 32:
406                 if (len > 17)
407                         return 0;
408                 if (ptransp) {
409                         for (i = 0; i < len; i++)
410                                 ((u32 *) info->pseudo_palette)[i] =
411                                     ((*(ptransp + i) & 0xFF00) << 16) |
412                                     ((*(pred + i) & 0xFF00) << 8) |
413                                     ((*(pgreen + i) & 0xFF00)) |
414                                     ((*(pblue + i) & 0xFF00) >> 8);
415                 } else {
416                         for (i = 0; i < len; i++)
417                                 ((u32 *) info->pseudo_palette)[i] =
418                                     0x00000000 |
419                                     ((*(pred + i) & 0xFF00) << 8) |
420                                     ((*(pgreen + i) & 0xFF00)) |
421                                     ((*(pblue + i) & 0xFF00) >> 8);
422                 }
423                 break;
424         }
425         return 0;
426 }
427
428 static int viafb_pan_display(struct fb_var_screeninfo *var,
429         struct fb_info *info)
430 {
431         unsigned int offset;
432
433         DEBUG_MSG(KERN_INFO "viafb_pan_display!\n");
434
435         offset = (var->xoffset + (var->yoffset * var->xres_virtual)) *
436             var->bits_per_pixel / 16;
437
438         DEBUG_MSG(KERN_INFO "\nviafb_pan_display,offset =%d ", offset);
439         viafb_set_primary_address(offset);
440         return 0;
441 }
442
443 static int viafb_blank(int blank_mode, struct fb_info *info)
444 {
445         DEBUG_MSG(KERN_INFO "viafb_blank!\n");
446         /* clear DPMS setting */
447
448         switch (blank_mode) {
449         case FB_BLANK_UNBLANK:
450                 /* Screen: On, HSync: On, VSync: On */
451                 /* control CRT monitor power management */
452                 viafb_write_reg_mask(CR36, VIACR, 0x00, BIT4 + BIT5);
453                 break;
454         case FB_BLANK_HSYNC_SUSPEND:
455                 /* Screen: Off, HSync: Off, VSync: On */
456                 /* control CRT monitor power management */
457                 viafb_write_reg_mask(CR36, VIACR, 0x10, BIT4 + BIT5);
458                 break;
459         case FB_BLANK_VSYNC_SUSPEND:
460                 /* Screen: Off, HSync: On, VSync: Off */
461                 /* control CRT monitor power management */
462                 viafb_write_reg_mask(CR36, VIACR, 0x20, BIT4 + BIT5);
463                 break;
464         case FB_BLANK_POWERDOWN:
465                 /* Screen: Off, HSync: Off, VSync: Off */
466                 /* control CRT monitor power management */
467                 viafb_write_reg_mask(CR36, VIACR, 0x30, BIT4 + BIT5);
468                 break;
469         }
470
471         return 0;
472 }
473
474 static int viafb_ioctl(struct fb_info *info, u_int cmd, u_long arg)
475 {
476         union {
477                 struct viafb_ioctl_mode viamode;
478                 struct viafb_ioctl_samm viasamm;
479                 struct viafb_driver_version driver_version;
480                 struct fb_var_screeninfo sec_var;
481                 struct _panel_size_pos_info panel_pos_size_para;
482                 struct viafb_ioctl_setting viafb_setting;
483                 struct device_t active_dev;
484         } u;
485         u32 state_info = 0;
486         u32 *viafb_gamma_table;
487         char driver_name[] = "viafb";
488
489         u32 __user *argp = (u32 __user *) arg;
490         u32 gpu32;
491         u32 video_dev_info = 0;
492
493         DEBUG_MSG(KERN_INFO "viafb_ioctl: 0x%X !!\n", cmd);
494         memset(&u, 0, sizeof(u));
495
496         switch (cmd) {
497         case VIAFB_GET_CHIP_INFO:
498                 if (copy_to_user(argp, viaparinfo->chip_info,
499                                 sizeof(struct chip_information)))
500                         return -EFAULT;
501                 break;
502         case VIAFB_GET_INFO_SIZE:
503                 return put_user((u32)sizeof(struct viafb_ioctl_info), argp);
504         case VIAFB_GET_INFO:
505                 return viafb_ioctl_get_viafb_info(arg);
506         case VIAFB_HOTPLUG:
507                 return put_user(viafb_ioctl_hotplug(info->var.xres,
508                                               info->var.yres,
509                                               info->var.bits_per_pixel), argp);
510         case VIAFB_SET_HOTPLUG_FLAG:
511                 if (copy_from_user(&gpu32, argp, sizeof(gpu32)))
512                         return -EFAULT;
513                 viafb_hotplug = (gpu32) ? 1 : 0;
514                 break;
515         case VIAFB_GET_RESOLUTION:
516                 u.viamode.xres = (u32) viafb_hotplug_Xres;
517                 u.viamode.yres = (u32) viafb_hotplug_Yres;
518                 u.viamode.refresh = (u32) viafb_hotplug_refresh;
519                 u.viamode.bpp = (u32) viafb_hotplug_bpp;
520                 if (viafb_SAMM_ON == 1) {
521                         u.viamode.xres_sec = viafb_second_xres;
522                         u.viamode.yres_sec = viafb_second_yres;
523                         u.viamode.virtual_xres_sec = viafb_second_virtual_xres;
524                         u.viamode.virtual_yres_sec = viafb_second_virtual_yres;
525                         u.viamode.refresh_sec = viafb_refresh1;
526                         u.viamode.bpp_sec = viafb_bpp1;
527                 } else {
528                         u.viamode.xres_sec = 0;
529                         u.viamode.yres_sec = 0;
530                         u.viamode.virtual_xres_sec = 0;
531                         u.viamode.virtual_yres_sec = 0;
532                         u.viamode.refresh_sec = 0;
533                         u.viamode.bpp_sec = 0;
534                 }
535                 if (copy_to_user(argp, &u.viamode, sizeof(u.viamode)))
536                         return -EFAULT;
537                 break;
538         case VIAFB_GET_SAMM_INFO:
539                 u.viasamm.samm_status = viafb_SAMM_ON;
540
541                 if (viafb_SAMM_ON == 1) {
542                         if (viafb_dual_fb) {
543                                 u.viasamm.size_prim = viaparinfo->fbmem_free;
544                                 u.viasamm.size_sec = viaparinfo1->fbmem_free;
545                         } else {
546                                 if (viafb_second_size) {
547                                         u.viasamm.size_prim =
548                                             viaparinfo->fbmem_free -
549                                             viafb_second_size * 1024 * 1024;
550                                         u.viasamm.size_sec =
551                                             viafb_second_size * 1024 * 1024;
552                                 } else {
553                                         u.viasamm.size_prim =
554                                             viaparinfo->fbmem_free >> 1;
555                                         u.viasamm.size_sec =
556                                             (viaparinfo->fbmem_free >> 1);
557                                 }
558                         }
559                         u.viasamm.mem_base = viaparinfo->fbmem;
560                         u.viasamm.offset_sec = viafb_second_offset;
561                 } else {
562                         u.viasamm.size_prim =
563                             viaparinfo->memsize - viaparinfo->fbmem_used;
564                         u.viasamm.size_sec = 0;
565                         u.viasamm.mem_base = viaparinfo->fbmem;
566                         u.viasamm.offset_sec = 0;
567                 }
568
569                 if (copy_to_user(argp, &u.viasamm, sizeof(u.viasamm)))
570                         return -EFAULT;
571
572                 break;
573         case VIAFB_TURN_ON_OUTPUT_DEVICE:
574                 if (copy_from_user(&gpu32, argp, sizeof(gpu32)))
575                         return -EFAULT;
576                 if (gpu32 & CRT_Device)
577                         viafb_crt_enable();
578                 if (gpu32 & DVI_Device)
579                         viafb_dvi_enable();
580                 if (gpu32 & LCD_Device)
581                         viafb_lcd_enable();
582                 break;
583         case VIAFB_TURN_OFF_OUTPUT_DEVICE:
584                 if (copy_from_user(&gpu32, argp, sizeof(gpu32)))
585                         return -EFAULT;
586                 if (gpu32 & CRT_Device)
587                         viafb_crt_disable();
588                 if (gpu32 & DVI_Device)
589                         viafb_dvi_disable();
590                 if (gpu32 & LCD_Device)
591                         viafb_lcd_disable();
592                 break;
593         case VIAFB_SET_DEVICE:
594                 if (copy_from_user(&u.active_dev, (void *)argp,
595                         sizeof(u.active_dev)))
596                         return -EFAULT;
597                 viafb_set_device(u.active_dev);
598                 viafb_set_par(info);
599                 break;
600         case VIAFB_GET_DEVICE:
601                 u.active_dev.crt = viafb_CRT_ON;
602                 u.active_dev.dvi = viafb_DVI_ON;
603                 u.active_dev.lcd = viafb_LCD_ON;
604                 u.active_dev.samm = viafb_SAMM_ON;
605                 u.active_dev.primary_dev = viafb_primary_dev;
606
607                 u.active_dev.lcd_dsp_cent = viafb_lcd_dsp_method;
608                 u.active_dev.lcd_panel_id = viafb_lcd_panel_id;
609                 u.active_dev.lcd_mode = viafb_lcd_mode;
610
611                 u.active_dev.xres = viafb_hotplug_Xres;
612                 u.active_dev.yres = viafb_hotplug_Yres;
613
614                 u.active_dev.xres1 = viafb_second_xres;
615                 u.active_dev.yres1 = viafb_second_yres;
616
617                 u.active_dev.bpp = viafb_bpp;
618                 u.active_dev.bpp1 = viafb_bpp1;
619                 u.active_dev.refresh = viafb_refresh;
620                 u.active_dev.refresh1 = viafb_refresh1;
621
622                 u.active_dev.epia_dvi = viafb_platform_epia_dvi;
623                 u.active_dev.lcd_dual_edge = viafb_device_lcd_dualedge;
624                 u.active_dev.bus_width = viafb_bus_width;
625
626                 if (copy_to_user(argp, &u.active_dev, sizeof(u.active_dev)))
627                         return -EFAULT;
628                 break;
629
630         case VIAFB_GET_DRIVER_VERSION:
631                 u.driver_version.iMajorNum = VERSION_MAJOR;
632                 u.driver_version.iKernelNum = VERSION_KERNEL;
633                 u.driver_version.iOSNum = VERSION_OS;
634                 u.driver_version.iMinorNum = VERSION_MINOR;
635
636                 if (copy_to_user(argp, &u.driver_version,
637                         sizeof(u.driver_version)))
638                         return -EFAULT;
639
640                 break;
641
642         case VIAFB_SET_DEVICE_INFO:
643                 if (copy_from_user(&u.viafb_setting,
644                         argp, sizeof(u.viafb_setting)))
645                         return -EFAULT;
646                 if (apply_device_setting(u.viafb_setting, info) < 0)
647                         return -EINVAL;
648
649                 break;
650
651         case VIAFB_SET_SECOND_MODE:
652                 if (copy_from_user(&u.sec_var, argp, sizeof(u.sec_var)))
653                         return -EFAULT;
654                 apply_second_mode_setting(&u.sec_var);
655                 break;
656
657         case VIAFB_GET_DEVICE_INFO:
658
659                 retrieve_device_setting(&u.viafb_setting);
660
661                 if (copy_to_user(argp, &u.viafb_setting,
662                                  sizeof(u.viafb_setting)))
663                         return -EFAULT;
664
665                 break;
666
667         case VIAFB_GET_DEVICE_SUPPORT:
668                 viafb_get_device_support_state(&state_info);
669                 if (put_user(state_info, argp))
670                         return -EFAULT;
671                 break;
672
673         case VIAFB_GET_DEVICE_CONNECT:
674                 viafb_get_device_connect_state(&state_info);
675                 if (put_user(state_info, argp))
676                         return -EFAULT;
677                 break;
678
679         case VIAFB_GET_PANEL_SUPPORT_EXPAND:
680                 state_info =
681                     viafb_lcd_get_support_expand_state(info->var.xres,
682                                                  info->var.yres);
683                 if (put_user(state_info, argp))
684                         return -EFAULT;
685                 break;
686
687         case VIAFB_GET_DRIVER_NAME:
688                 if (copy_to_user(argp, driver_name, sizeof(driver_name)))
689                         return -EFAULT;
690                 break;
691
692         case VIAFB_SET_GAMMA_LUT:
693                 viafb_gamma_table = kmalloc(256 * sizeof(u32), GFP_KERNEL);
694                 if (!viafb_gamma_table)
695                         return -ENOMEM;
696                 if (copy_from_user(viafb_gamma_table, argp,
697                                 sizeof(viafb_gamma_table))) {
698                         kfree(viafb_gamma_table);
699                         return -EFAULT;
700                 }
701                 viafb_set_gamma_table(viafb_bpp, viafb_gamma_table);
702                 kfree(viafb_gamma_table);
703                 break;
704
705         case VIAFB_GET_GAMMA_LUT:
706                 viafb_gamma_table = kmalloc(256 * sizeof(u32), GFP_KERNEL);
707                 if (!viafb_gamma_table)
708                         return -ENOMEM;
709                 viafb_get_gamma_table(viafb_gamma_table);
710                 if (copy_to_user(argp, viafb_gamma_table,
711                         sizeof(viafb_gamma_table))) {
712                         kfree(viafb_gamma_table);
713                         return -EFAULT;
714                 }
715                 kfree(viafb_gamma_table);
716                 break;
717
718         case VIAFB_GET_GAMMA_SUPPORT_STATE:
719                 viafb_get_gamma_support_state(viafb_bpp, &state_info);
720                 if (put_user(state_info, argp))
721                         return -EFAULT;
722                 break;
723         case VIAFB_SET_VIDEO_DEVICE:
724                 get_user(video_dev_info, argp);
725                 viafb_set_video_device(video_dev_info);
726                 break;
727         case VIAFB_GET_VIDEO_DEVICE:
728                 viafb_get_video_device(&video_dev_info);
729                 if (put_user(video_dev_info, argp))
730                         return -EFAULT;
731                 break;
732         case VIAFB_SYNC_SURFACE:
733                 DEBUG_MSG(KERN_INFO "lobo VIAFB_SYNC_SURFACE\n");
734                 break;
735         case VIAFB_GET_DRIVER_CAPS:
736                 break;
737
738         case VIAFB_GET_PANEL_MAX_SIZE:
739                 if (copy_from_user(&u.panel_pos_size_para, argp,
740                                    sizeof(u.panel_pos_size_para)))
741                         return -EFAULT;
742                 u.panel_pos_size_para.x = u.panel_pos_size_para.y = 0;
743                 if (copy_to_user(argp, &u.panel_pos_size_para,
744                      sizeof(u.panel_pos_size_para)))
745                         return -EFAULT;
746                 break;
747         case VIAFB_GET_PANEL_MAX_POSITION:
748                 if (copy_from_user(&u.panel_pos_size_para, argp,
749                                    sizeof(u.panel_pos_size_para)))
750                         return -EFAULT;
751                 u.panel_pos_size_para.x = u.panel_pos_size_para.y = 0;
752                 if (copy_to_user(argp, &u.panel_pos_size_para,
753                                  sizeof(u.panel_pos_size_para)))
754                         return -EFAULT;
755                 break;
756
757         case VIAFB_GET_PANEL_POSITION:
758                 if (copy_from_user(&u.panel_pos_size_para, argp,
759                                    sizeof(u.panel_pos_size_para)))
760                         return -EFAULT;
761                 u.panel_pos_size_para.x = u.panel_pos_size_para.y = 0;
762                 if (copy_to_user(argp, &u.panel_pos_size_para,
763                                  sizeof(u.panel_pos_size_para)))
764                         return -EFAULT;
765                 break;
766         case VIAFB_GET_PANEL_SIZE:
767                 if (copy_from_user(&u.panel_pos_size_para, argp,
768                                    sizeof(u.panel_pos_size_para)))
769                         return -EFAULT;
770                 u.panel_pos_size_para.x = u.panel_pos_size_para.y = 0;
771                 if (copy_to_user(argp, &u.panel_pos_size_para,
772                                  sizeof(u.panel_pos_size_para)))
773                         return -EFAULT;
774                 break;
775
776         case VIAFB_SET_PANEL_POSITION:
777                 if (copy_from_user(&u.panel_pos_size_para, argp,
778                                    sizeof(u.panel_pos_size_para)))
779                         return -EFAULT;
780                 break;
781         case VIAFB_SET_PANEL_SIZE:
782                 if (copy_from_user(&u.panel_pos_size_para, argp,
783                                    sizeof(u.panel_pos_size_para)))
784                         return -EFAULT;
785                 break;
786
787         default:
788                 return -EINVAL;
789         }
790
791         return 0;
792 }
793
794 static void viafb_fillrect(struct fb_info *info,
795         const struct fb_fillrect *rect)
796 {
797         u32 col = 0, rop = 0;
798         int pitch;
799
800         if (!viafb_accel) {
801                 cfb_fillrect(info, rect);
802                 return;
803         }
804
805         if (!rect->width || !rect->height)
806                 return;
807
808         switch (rect->rop) {
809         case ROP_XOR:
810                 rop = 0x5A;
811                 break;
812         case ROP_COPY:
813         default:
814                 rop = 0xF0;
815                 break;
816         }
817
818         switch (info->var.bits_per_pixel) {
819         case 8:
820                 col = rect->color;
821                 break;
822         case 16:
823                 col = ((u32 *) (info->pseudo_palette))[rect->color];
824                 break;
825         case 32:
826                 col = ((u32 *) (info->pseudo_palette))[rect->color];
827                 break;
828         }
829
830         /* BitBlt Source Address */
831         writel(0x0, viaparinfo->io_virt + VIA_REG_SRCPOS);
832         /* Source Base Address */
833         writel(0x0, viaparinfo->io_virt + VIA_REG_SRCBASE);
834         /* Destination Base Address */
835         writel((info->fix.smem_start - viafbinfo->fix.smem_start) >> 3,
836                    viaparinfo->io_virt + VIA_REG_DSTBASE);
837         /* Pitch */
838         pitch = (info->var.xres_virtual + 7) & ~7;
839         writel(VIA_PITCH_ENABLE |
840                    (((pitch *
841                       info->var.bits_per_pixel >> 3) >> 3) |
842                       (((pitch * info->
843                       var.bits_per_pixel >> 3) >> 3) << 16)),
844                       viaparinfo->io_virt + VIA_REG_PITCH);
845         /* BitBlt Destination Address */
846         writel(((rect->dy << 16) | rect->dx),
847                 viaparinfo->io_virt + VIA_REG_DSTPOS);
848         /* Dimension: width & height */
849         writel((((rect->height - 1) << 16) | (rect->width - 1)),
850                 viaparinfo->io_virt + VIA_REG_DIMENSION);
851         /* Forground color or Destination color */
852         writel(col, viaparinfo->io_virt + VIA_REG_FGCOLOR);
853         /* GE Command */
854         writel((0x01 | 0x2000 | (rop << 24)),
855                 viaparinfo->io_virt + VIA_REG_GECMD);
856
857 }
858
859 static void viafb_copyarea(struct fb_info *info,
860         const struct fb_copyarea *area)
861 {
862         u32 dy = area->dy, sy = area->sy, direction = 0x0;
863         u32 sx = area->sx, dx = area->dx, width = area->width;
864         int pitch;
865
866         DEBUG_MSG(KERN_INFO "viafb_copyarea!!\n");
867
868         if (!viafb_accel) {
869                 cfb_copyarea(info, area);
870                 return;
871         }
872
873         if (!area->width || !area->height)
874                 return;
875
876         if (sy < dy) {
877                 dy += area->height - 1;
878                 sy += area->height - 1;
879                 direction |= 0x4000;
880         }
881
882         if (sx < dx) {
883                 dx += width - 1;
884                 sx += width - 1;
885                 direction |= 0x8000;
886         }
887
888         /* Source Base Address */
889         writel((info->fix.smem_start - viafbinfo->fix.smem_start) >> 3,
890                    viaparinfo->io_virt + VIA_REG_SRCBASE);
891         /* Destination Base Address */
892         writel((info->fix.smem_start - viafbinfo->fix.smem_start) >> 3,
893                    viaparinfo->io_virt + VIA_REG_DSTBASE);
894         /* Pitch */
895         pitch = (info->var.xres_virtual + 7) & ~7;
896         /* VIA_PITCH_ENABLE can be omitted now. */
897         writel(VIA_PITCH_ENABLE |
898                    (((pitch *
899                       info->var.bits_per_pixel >> 3) >> 3) | (((pitch *
900                                                                 info->var.
901                                                                 bits_per_pixel
902                                                                 >> 3) >> 3)
903                                                               << 16)),
904                                 viaparinfo->io_virt + VIA_REG_PITCH);
905         /* BitBlt Source Address */
906         writel(((sy << 16) | sx), viaparinfo->io_virt + VIA_REG_SRCPOS);
907         /* BitBlt Destination Address */
908         writel(((dy << 16) | dx), viaparinfo->io_virt + VIA_REG_DSTPOS);
909         /* Dimension: width & height */
910         writel((((area->height - 1) << 16) | (area->width - 1)),
911                    viaparinfo->io_virt + VIA_REG_DIMENSION);
912         /* GE Command */
913         writel((0x01 | direction | (0xCC << 24)),
914                 viaparinfo->io_virt + VIA_REG_GECMD);
915
916 }
917
918 static void viafb_imageblit(struct fb_info *info,
919         const struct fb_image *image)
920 {
921         u32 size, bg_col = 0, fg_col = 0, *udata;
922         int i;
923         int pitch;
924
925         if (!viafb_accel) {
926                 cfb_imageblit(info, image);
927                 return;
928         }
929
930         udata = (u32 *) image->data;
931
932         switch (info->var.bits_per_pixel) {
933         case 8:
934                 bg_col = image->bg_color;
935                 fg_col = image->fg_color;
936                 break;
937         case 16:
938                 bg_col = ((u32 *) (info->pseudo_palette))[image->bg_color];
939                 fg_col = ((u32 *) (info->pseudo_palette))[image->fg_color];
940                 break;
941         case 32:
942                 bg_col = ((u32 *) (info->pseudo_palette))[image->bg_color];
943                 fg_col = ((u32 *) (info->pseudo_palette))[image->fg_color];
944                 break;
945         }
946         size = image->width * image->height;
947
948         /* Source Base Address */
949         writel(0x0, viaparinfo->io_virt + VIA_REG_SRCBASE);
950         /* Destination Base Address */
951         writel((info->fix.smem_start - viafbinfo->fix.smem_start) >> 3,
952                    viaparinfo->io_virt + VIA_REG_DSTBASE);
953         /* Pitch */
954         pitch = (info->var.xres_virtual + 7) & ~7;
955         writel(VIA_PITCH_ENABLE |
956                    (((pitch *
957                       info->var.bits_per_pixel >> 3) >> 3) | (((pitch *
958                                                                 info->var.
959                                                                 bits_per_pixel
960                                                                 >> 3) >> 3)
961                                                               << 16)),
962                                 viaparinfo->io_virt + VIA_REG_PITCH);
963         /* BitBlt Source Address */
964         writel(0x0, viaparinfo->io_virt + VIA_REG_SRCPOS);
965         /* BitBlt Destination Address */
966         writel(((image->dy << 16) | image->dx),
967                 viaparinfo->io_virt + VIA_REG_DSTPOS);
968         /* Dimension: width & height */
969         writel((((image->height - 1) << 16) | (image->width - 1)),
970                    viaparinfo->io_virt + VIA_REG_DIMENSION);
971         /* fb color */
972         writel(fg_col, viaparinfo->io_virt + VIA_REG_FGCOLOR);
973         /* bg color */
974         writel(bg_col, viaparinfo->io_virt + VIA_REG_BGCOLOR);
975         /* GE Command */
976         writel(0xCC020142, viaparinfo->io_virt + VIA_REG_GECMD);
977
978         for (i = 0; i < size / 4; i++) {
979                 writel(*udata, viaparinfo->io_virt + VIA_MMIO_BLTBASE);
980                 udata++;
981         }
982
983 }
984
985 static int viafb_cursor(struct fb_info *info, struct fb_cursor *cursor)
986 {
987         u32 temp, xx, yy, bg_col = 0, fg_col = 0;
988         int i, j = 0;
989         static int hw_cursor;
990         struct viafb_par *p_viafb_par;
991
992         if (viafb_accel)
993                 hw_cursor = 1;
994
995         if (!viafb_accel) {
996                 if (hw_cursor) {
997                         viafb_show_hw_cursor(info, HW_Cursor_OFF);
998                         hw_cursor = 0;
999                 }
1000                 return -ENODEV;
1001         }
1002
1003         if ((((struct viafb_par *)(info->par))->iga_path == IGA2)
1004             && (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266))
1005                 return -ENODEV;
1006
1007         /* When duoview and using lcd , use soft cursor */
1008         if (viafb_LCD_ON || (!viafb_SAMM_ON &&
1009                 viafb_LCD2_ON + viafb_DVI_ON + viafb_CRT_ON == 2))
1010                 return -ENODEV;
1011
1012         viafb_show_hw_cursor(info, HW_Cursor_OFF);
1013         viacursor = *cursor;
1014
1015         if (cursor->set & FB_CUR_SETHOT) {
1016                 viacursor.hot = cursor->hot;
1017                 temp = ((viacursor.hot.x) << 16) + viacursor.hot.y;
1018                 writel(temp, viaparinfo->io_virt + VIA_REG_CURSOR_ORG);
1019         }
1020
1021         if (cursor->set & FB_CUR_SETPOS) {
1022                 viacursor.image.dx = cursor->image.dx;
1023                 viacursor.image.dy = cursor->image.dy;
1024                 yy = cursor->image.dy - info->var.yoffset;
1025                 xx = cursor->image.dx - info->var.xoffset;
1026                 temp = yy & 0xFFFF;
1027                 temp |= (xx << 16);
1028                 writel(temp, viaparinfo->io_virt + VIA_REG_CURSOR_POS);
1029         }
1030
1031         if (cursor->set & FB_CUR_SETSIZE) {
1032                 temp = readl(viaparinfo->io_virt + VIA_REG_CURSOR_MODE);
1033
1034                 if ((cursor->image.width <= 32)
1035                     && (cursor->image.height <= 32)) {
1036                         MAX_CURS = 32;
1037                         temp |= 0x2;
1038                 } else if ((cursor->image.width <= 64)
1039                            && (cursor->image.height <= 64)) {
1040                         MAX_CURS = 64;
1041                         temp &= 0xFFFFFFFD;
1042                 } else {
1043                         DEBUG_MSG(KERN_INFO
1044                         "The cursor image is biger than 64x64 bits...\n");
1045                         return -ENXIO;
1046                 }
1047                 writel(temp, viaparinfo->io_virt + VIA_REG_CURSOR_MODE);
1048
1049                 viacursor.image.height = cursor->image.height;
1050                 viacursor.image.width = cursor->image.width;
1051         }
1052
1053         if (cursor->set & FB_CUR_SETCMAP) {
1054                 viacursor.image.fg_color = cursor->image.fg_color;
1055                 viacursor.image.bg_color = cursor->image.bg_color;
1056
1057                 switch (info->var.bits_per_pixel) {
1058                 case 8:
1059                 case 16:
1060                 case 32:
1061                         bg_col =
1062                             (0xFF << 24) |
1063                             (((info->cmap.red)[viacursor.image.bg_color] &
1064                             0xFF00) << 8) |
1065                             ((info->cmap.green)[viacursor.image.bg_color] &
1066                             0xFF00) |
1067                             (((info->cmap.blue)[viacursor.image.bg_color] &
1068                             0xFF00) >> 8);
1069                         fg_col =
1070                             (0xFF << 24) |
1071                             (((info->cmap.red)[viacursor.image.fg_color] &
1072                             0xFF00) << 8) |
1073                             ((info->cmap.green)[viacursor.image.fg_color] &
1074                             0xFF00) |
1075                             (((info->cmap.blue)[viacursor.image.fg_color] &
1076                             0xFF00) >> 8);
1077                         break;
1078                 default:
1079                         return 0;
1080                 }
1081
1082                 /* This is indeed a patch for VT3324/VT3353 */
1083                 if (!info->par)
1084                         return 0;
1085                 p_viafb_par = (struct viafb_par *)info->par;
1086
1087                 if ((p_viafb_par->chip_info->gfx_chip_name ==
1088                         UNICHROME_CX700) ||
1089                         ((p_viafb_par->chip_info->gfx_chip_name ==
1090                         UNICHROME_VX800))) {
1091                         bg_col =
1092                             (((info->cmap.red)[viacursor.image.bg_color] &
1093                             0xFFC0) << 14) |
1094                             (((info->cmap.green)[viacursor.image.bg_color] &
1095                             0xFFC0) << 4) |
1096                             (((info->cmap.blue)[viacursor.image.bg_color] &
1097                             0xFFC0) >> 6);
1098                         fg_col =
1099                             (((info->cmap.red)[viacursor.image.fg_color] &
1100                             0xFFC0) << 14) |
1101                             (((info->cmap.green)[viacursor.image.fg_color] &
1102                             0xFFC0) << 4) |
1103                             (((info->cmap.blue)[viacursor.image.fg_color] &
1104                             0xFFC0) >> 6);
1105                 }
1106
1107                 writel(bg_col, viaparinfo->io_virt + VIA_REG_CURSOR_BG);
1108                 writel(fg_col, viaparinfo->io_virt + VIA_REG_CURSOR_FG);
1109         }
1110
1111         if (cursor->set & FB_CUR_SETSHAPE) {
1112                 struct {
1113                         u8 data[CURSOR_SIZE / 8];
1114                         u32 bak[CURSOR_SIZE / 32];
1115                 } *cr_data = kzalloc(sizeof(*cr_data), GFP_ATOMIC);
1116                 int size =
1117                     ((viacursor.image.width + 7) >> 3) *
1118                     viacursor.image.height;
1119
1120                 if (cr_data == NULL)
1121                         goto out;
1122
1123                 if (MAX_CURS == 32) {
1124                         for (i = 0; i < (CURSOR_SIZE / 32); i++) {
1125                                 cr_data->bak[i] = 0x0;
1126                                 cr_data->bak[i + 1] = 0xFFFFFFFF;
1127                                 i += 1;
1128                         }
1129                 } else if (MAX_CURS == 64) {
1130                         for (i = 0; i < (CURSOR_SIZE / 32); i++) {
1131                                 cr_data->bak[i] = 0x0;
1132                                 cr_data->bak[i + 1] = 0x0;
1133                                 cr_data->bak[i + 2] = 0xFFFFFFFF;
1134                                 cr_data->bak[i + 3] = 0xFFFFFFFF;
1135                                 i += 3;
1136                         }
1137                 }
1138
1139                 switch (viacursor.rop) {
1140                 case ROP_XOR:
1141                         for (i = 0; i < size; i++)
1142                                 cr_data->data[i] = viacursor.mask[i];
1143                         break;
1144                 case ROP_COPY:
1145
1146                         for (i = 0; i < size; i++)
1147                                 cr_data->data[i] = viacursor.mask[i];
1148                         break;
1149                 default:
1150                         break;
1151                 }
1152
1153                 if (MAX_CURS == 32) {
1154                         for (i = 0; i < size; i++) {
1155                                 cr_data->bak[j] = (u32) cr_data->data[i];
1156                                 cr_data->bak[j + 1] = ~cr_data->bak[j];
1157                                 j += 2;
1158                         }
1159                 } else if (MAX_CURS == 64) {
1160                         for (i = 0; i < size; i++) {
1161                                 cr_data->bak[j] = (u32) cr_data->data[i];
1162                                 cr_data->bak[j + 1] = 0x0;
1163                                 cr_data->bak[j + 2] = ~cr_data->bak[j];
1164                                 cr_data->bak[j + 3] = ~cr_data->bak[j + 1];
1165                                 j += 4;
1166                         }
1167                 }
1168
1169                 memcpy(viafbinfo->screen_base +
1170                        ((struct viafb_par *)(info->par))->cursor_start,
1171                        cr_data->bak, CURSOR_SIZE);
1172 out:
1173                 kfree(cr_data);
1174         }
1175
1176         if (viacursor.enable)
1177                 viafb_show_hw_cursor(info, HW_Cursor_ON);
1178
1179         return 0;
1180 }
1181
1182 static int viafb_sync(struct fb_info *info)
1183 {
1184         if (viafb_accel)
1185                 viafb_wait_engine_idle();
1186         return 0;
1187 }
1188
1189 int viafb_get_mode_index(int hres, int vres)
1190 {
1191         u32 i;
1192         DEBUG_MSG(KERN_INFO "viafb_get_mode_index!\n");
1193
1194         for (i = 0; i < NUM_TOTAL_MODETABLE; i++)
1195                 if (CLE266Modes[i].mode_array &&
1196                         CLE266Modes[i].crtc[0].crtc.hor_addr == hres &&
1197                         CLE266Modes[i].crtc[0].crtc.ver_addr == vres)
1198                         break;
1199
1200         if (i == NUM_TOTAL_MODETABLE)
1201                 return VIA_RES_INVALID;
1202
1203         return CLE266Modes[i].ModeIndex;
1204 }
1205
1206 static void check_available_device_to_enable(int device_id)
1207 {
1208         int device_num = 0;
1209
1210         /* Initialize: */
1211         viafb_CRT_ON = STATE_OFF;
1212         viafb_DVI_ON = STATE_OFF;
1213         viafb_LCD_ON = STATE_OFF;
1214         viafb_LCD2_ON = STATE_OFF;
1215         viafb_DeviceStatus = None_Device;
1216
1217         if ((device_id & CRT_Device) && (device_num < MAX_ACTIVE_DEV_NUM)) {
1218                 viafb_CRT_ON = STATE_ON;
1219                 device_num++;
1220                 viafb_DeviceStatus |= CRT_Device;
1221         }
1222
1223         if ((device_id & DVI_Device) && (device_num < MAX_ACTIVE_DEV_NUM)) {
1224                 viafb_DVI_ON = STATE_ON;
1225                 device_num++;
1226                 viafb_DeviceStatus |= DVI_Device;
1227         }
1228
1229         if ((device_id & LCD_Device) && (device_num < MAX_ACTIVE_DEV_NUM)) {
1230                 viafb_LCD_ON = STATE_ON;
1231                 device_num++;
1232                 viafb_DeviceStatus |= LCD_Device;
1233         }
1234
1235         if ((device_id & LCD2_Device) && (device_num < MAX_ACTIVE_DEV_NUM)) {
1236                 viafb_LCD2_ON = STATE_ON;
1237                 device_num++;
1238                 viafb_DeviceStatus |= LCD2_Device;
1239         }
1240
1241         if (viafb_DeviceStatus == None_Device) {
1242                 /* Use CRT as default active device: */
1243                 viafb_CRT_ON = STATE_ON;
1244                 viafb_DeviceStatus = CRT_Device;
1245         }
1246         DEBUG_MSG(KERN_INFO "Device Status:%x", viafb_DeviceStatus);
1247 }
1248
1249 static void viafb_set_device(struct device_t active_dev)
1250 {
1251         /* Check available device to enable: */
1252         int device_id = None_Device;
1253         if (active_dev.crt)
1254                 device_id |= CRT_Device;
1255         if (active_dev.dvi)
1256                 device_id |= DVI_Device;
1257         if (active_dev.lcd)
1258                 device_id |= LCD_Device;
1259
1260         check_available_device_to_enable(device_id);
1261
1262         /* Check property of LCD: */
1263         if (viafb_LCD_ON) {
1264                 if (active_dev.lcd_dsp_cent) {
1265                         viaparinfo->lvds_setting_info->display_method =
1266                                 viafb_lcd_dsp_method = LCD_CENTERING;
1267                 } else {
1268                         viaparinfo->lvds_setting_info->display_method =
1269                                 viafb_lcd_dsp_method = LCD_EXPANDSION;
1270                 }
1271
1272                 if (active_dev.lcd_mode == LCD_SPWG) {
1273                         viaparinfo->lvds_setting_info->lcd_mode =
1274                                 viafb_lcd_mode = LCD_SPWG;
1275                 } else {
1276                         viaparinfo->lvds_setting_info->lcd_mode =
1277                                 viafb_lcd_mode = LCD_OPENLDI;
1278                 }
1279
1280                 if (active_dev.lcd_panel_id <= LCD_PANEL_ID_MAXIMUM) {
1281                         viafb_lcd_panel_id = active_dev.lcd_panel_id;
1282                         viafb_init_lcd_size();
1283                 }
1284         }
1285
1286         /* Check property of mode: */
1287         if (!active_dev.xres1)
1288                 viafb_second_xres = 640;
1289         else
1290                 viafb_second_xres = active_dev.xres1;
1291         if (!active_dev.yres1)
1292                 viafb_second_yres = 480;
1293         else
1294                 viafb_second_yres = active_dev.yres1;
1295         if (active_dev.bpp != 0)
1296                 viafb_bpp = active_dev.bpp;
1297         if (active_dev.bpp1 != 0)
1298                 viafb_bpp1 = active_dev.bpp1;
1299         if (active_dev.refresh != 0)
1300                 viafb_refresh = active_dev.refresh;
1301         if (active_dev.refresh1 != 0)
1302                 viafb_refresh1 = active_dev.refresh1;
1303         if ((active_dev.samm == STATE_OFF) || (active_dev.samm == STATE_ON))
1304                 viafb_SAMM_ON = active_dev.samm;
1305         viafb_primary_dev = active_dev.primary_dev;
1306
1307         viafb_set_primary_address(0);
1308         viafb_set_secondary_address(viafb_SAMM_ON ? viafb_second_offset : 0);
1309         viafb_set_iga_path();
1310 }
1311
1312 static void viafb_set_video_device(u32 video_dev_info)
1313 {
1314         viaparinfo->video_on_crt = STATE_OFF;
1315         viaparinfo->video_on_dvi = STATE_OFF;
1316         viaparinfo->video_on_lcd = STATE_OFF;
1317
1318         /* Check available device to enable: */
1319         if ((video_dev_info & CRT_Device) == CRT_Device)
1320                 viaparinfo->video_on_crt = STATE_ON;
1321         else if ((video_dev_info & DVI_Device) == DVI_Device)
1322                 viaparinfo->video_on_dvi = STATE_ON;
1323         else if ((video_dev_info & LCD_Device) == LCD_Device)
1324                 viaparinfo->video_on_lcd = STATE_ON;
1325 }
1326
1327 static void viafb_get_video_device(u32 *video_dev_info)
1328 {
1329         *video_dev_info = None_Device;
1330         if (viaparinfo->video_on_crt == STATE_ON)
1331                 *video_dev_info |= CRT_Device;
1332         else if (viaparinfo->video_on_dvi == STATE_ON)
1333                 *video_dev_info |= DVI_Device;
1334         else if (viaparinfo->video_on_lcd == STATE_ON)
1335                 *video_dev_info |= LCD_Device;
1336 }
1337
1338 static int get_primary_device(void)
1339 {
1340         int primary_device = 0;
1341         /* Rule: device on iga1 path are the primary device. */
1342         if (viafb_SAMM_ON) {
1343                 if (viafb_CRT_ON) {
1344                         if (viaparinfo->crt_setting_info->iga_path == IGA1) {
1345                                 DEBUG_MSG(KERN_INFO "CRT IGA Path:%d\n",
1346                                         viaparinfo->
1347                                         crt_setting_info->iga_path);
1348                                 primary_device = CRT_Device;
1349                         }
1350                 }
1351                 if (viafb_DVI_ON) {
1352                         if (viaparinfo->tmds_setting_info->iga_path == IGA1) {
1353                                 DEBUG_MSG(KERN_INFO "DVI IGA Path:%d\n",
1354                                         viaparinfo->
1355                                         tmds_setting_info->iga_path);
1356                                 primary_device = DVI_Device;
1357                         }
1358                 }
1359                 if (viafb_LCD_ON) {
1360                         if (viaparinfo->lvds_setting_info->iga_path == IGA1) {
1361                                 DEBUG_MSG(KERN_INFO "LCD IGA Path:%d\n",
1362                                         viaparinfo->
1363                                         lvds_setting_info->iga_path);
1364                                 primary_device = LCD_Device;
1365                         }
1366                 }
1367                 if (viafb_LCD2_ON) {
1368                         if (viaparinfo->lvds_setting_info2->iga_path == IGA1) {
1369                                 DEBUG_MSG(KERN_INFO "LCD2 IGA Path:%d\n",
1370                                         viaparinfo->
1371                                         lvds_setting_info2->iga_path);
1372                                 primary_device = LCD2_Device;
1373                         }
1374                 }
1375         }
1376         return primary_device;
1377 }
1378
1379 static void apply_second_mode_setting(struct fb_var_screeninfo
1380         *sec_var)
1381 {
1382         u32 htotal, vtotal, long_refresh;
1383
1384         htotal = sec_var->xres + sec_var->left_margin +
1385                 sec_var->right_margin + sec_var->hsync_len;
1386         vtotal = sec_var->yres + sec_var->upper_margin +
1387                 sec_var->lower_margin + sec_var->vsync_len;
1388         if ((sec_var->xres_virtual * (sec_var->bits_per_pixel >> 3)) & 0x1F) {
1389                 /*Is 32 bytes alignment? */
1390                 /*32 pixel alignment */
1391                 sec_var->xres_virtual = (sec_var->xres_virtual + 31) & ~31;
1392         }
1393
1394         htotal = sec_var->xres + sec_var->left_margin +
1395                 sec_var->right_margin + sec_var->hsync_len;
1396         vtotal = sec_var->yres + sec_var->upper_margin +
1397                 sec_var->lower_margin + sec_var->vsync_len;
1398         long_refresh = 1000000000UL / sec_var->pixclock * 1000;
1399         long_refresh /= (htotal * vtotal);
1400
1401         viafb_second_xres = sec_var->xres;
1402         viafb_second_yres = sec_var->yres;
1403         viafb_second_virtual_xres = sec_var->xres_virtual;
1404         viafb_second_virtual_yres = sec_var->yres_virtual;
1405         viafb_bpp1 = sec_var->bits_per_pixel;
1406         viafb_refresh1 = viafb_get_refresh(sec_var->xres, sec_var->yres,
1407                 long_refresh);
1408 }
1409
1410 static int apply_device_setting(struct viafb_ioctl_setting setting_info,
1411         struct fb_info *info)
1412 {
1413         int need_set_mode = 0;
1414         DEBUG_MSG(KERN_INFO "apply_device_setting\n");
1415
1416         if (setting_info.device_flag) {
1417                 need_set_mode = 1;
1418                 check_available_device_to_enable(setting_info.device_status);
1419         }
1420
1421         /* Unlock LCD's operation according to LCD flag
1422            and check if the setting value is valid. */
1423         /* If the value is valid, apply the new setting value to the device. */
1424         if (viafb_LCD_ON) {
1425                 if (setting_info.lcd_operation_flag & OP_LCD_CENTERING) {
1426                         need_set_mode = 1;
1427                         if (setting_info.lcd_attributes.display_center) {
1428                                 /* Centering */
1429                                 viaparinfo->lvds_setting_info->display_method =
1430                                     LCD_CENTERING;
1431                                 viafb_lcd_dsp_method = LCD_CENTERING;
1432                                 viaparinfo->lvds_setting_info2->display_method =
1433                                     viafb_lcd_dsp_method = LCD_CENTERING;
1434                         } else {
1435                                 /* expandsion */
1436                                 viaparinfo->lvds_setting_info->display_method =
1437                                     LCD_EXPANDSION;
1438                                 viafb_lcd_dsp_method = LCD_EXPANDSION;
1439                                 viaparinfo->lvds_setting_info2->display_method =
1440                                     LCD_EXPANDSION;
1441                                 viafb_lcd_dsp_method = LCD_EXPANDSION;
1442                         }
1443                 }
1444
1445                 if (setting_info.lcd_operation_flag & OP_LCD_MODE) {
1446                         need_set_mode = 1;
1447                         if (setting_info.lcd_attributes.lcd_mode ==
1448                                 LCD_SPWG) {
1449                                 viaparinfo->lvds_setting_info->lcd_mode =
1450                                         viafb_lcd_mode = LCD_SPWG;
1451                         } else {
1452                                 viaparinfo->lvds_setting_info->lcd_mode =
1453                                         viafb_lcd_mode = LCD_OPENLDI;
1454                         }
1455                         viaparinfo->lvds_setting_info2->lcd_mode =
1456                             viaparinfo->lvds_setting_info->lcd_mode;
1457                 }
1458
1459                 if (setting_info.lcd_operation_flag & OP_LCD_PANEL_ID) {
1460                         need_set_mode = 1;
1461                         if (setting_info.lcd_attributes.panel_id <=
1462                             LCD_PANEL_ID_MAXIMUM) {
1463                                 viafb_lcd_panel_id =
1464                                     setting_info.lcd_attributes.panel_id;
1465                                 viafb_init_lcd_size();
1466                         }
1467                 }
1468         }
1469
1470         if (0 != (setting_info.samm_status & OP_SAMM)) {
1471                 setting_info.samm_status =
1472                     setting_info.samm_status & (~OP_SAMM);
1473                 if (setting_info.samm_status == 0
1474                     || setting_info.samm_status == 1) {
1475                         viafb_SAMM_ON = setting_info.samm_status;
1476
1477                         if (viafb_SAMM_ON)
1478                                 viafb_primary_dev = setting_info.primary_device;
1479
1480                         viafb_set_primary_address(0);
1481                         viafb_set_secondary_address(viafb_SAMM_ON ? viafb_second_offset : 0);
1482                         viafb_set_iga_path();
1483                 }
1484                 need_set_mode = 1;
1485         }
1486
1487         if (!need_set_mode) {
1488                 ;
1489         } else {
1490                 viafb_set_iga_path();
1491                 viafb_set_par(info);
1492         }
1493         return true;
1494 }
1495
1496 static void retrieve_device_setting(struct viafb_ioctl_setting
1497         *setting_info)
1498 {
1499
1500         /* get device status */
1501         if (viafb_CRT_ON == 1)
1502                 setting_info->device_status = CRT_Device;
1503         if (viafb_DVI_ON == 1)
1504                 setting_info->device_status |= DVI_Device;
1505         if (viafb_LCD_ON == 1)
1506                 setting_info->device_status |= LCD_Device;
1507         if (viafb_LCD2_ON == 1)
1508                 setting_info->device_status |= LCD2_Device;
1509         if ((viaparinfo->video_on_crt == 1) && (viafb_CRT_ON == 1)) {
1510                 setting_info->video_device_status =
1511                         viaparinfo->crt_setting_info->iga_path;
1512         } else if ((viaparinfo->video_on_dvi == 1) && (viafb_DVI_ON == 1)) {
1513                 setting_info->video_device_status =
1514                         viaparinfo->tmds_setting_info->iga_path;
1515         } else if ((viaparinfo->video_on_lcd == 1) && (viafb_LCD_ON == 1)) {
1516                 setting_info->video_device_status =
1517                         viaparinfo->lvds_setting_info->iga_path;
1518         } else {
1519                 setting_info->video_device_status = 0;
1520         }
1521
1522         setting_info->samm_status = viafb_SAMM_ON;
1523         setting_info->primary_device = get_primary_device();
1524
1525         setting_info->first_dev_bpp = viafb_bpp;
1526         setting_info->second_dev_bpp = viafb_bpp1;
1527
1528         setting_info->first_dev_refresh = viafb_refresh;
1529         setting_info->second_dev_refresh = viafb_refresh1;
1530
1531         setting_info->first_dev_hor_res = viafb_hotplug_Xres;
1532         setting_info->first_dev_ver_res = viafb_hotplug_Yres;
1533         setting_info->second_dev_hor_res = viafb_second_xres;
1534         setting_info->second_dev_ver_res = viafb_second_yres;
1535
1536         /* Get lcd attributes */
1537         setting_info->lcd_attributes.display_center = viafb_lcd_dsp_method;
1538         setting_info->lcd_attributes.panel_id = viafb_lcd_panel_id;
1539         setting_info->lcd_attributes.lcd_mode = viafb_lcd_mode;
1540 }
1541
1542 static void parse_active_dev(void)
1543 {
1544         viafb_CRT_ON = STATE_OFF;
1545         viafb_DVI_ON = STATE_OFF;
1546         viafb_LCD_ON = STATE_OFF;
1547         viafb_LCD2_ON = STATE_OFF;
1548         /* 1. Modify the active status of devices. */
1549         /* 2. Keep the order of devices, so we can set corresponding
1550            IGA path to devices in SAMM case. */
1551         /*    Note: The previous of active_dev is primary device,
1552            and the following is secondary device. */
1553         if (!strncmp(viafb_active_dev, "CRT+DVI", 7)) {
1554                 /* CRT+DVI */
1555                 viafb_CRT_ON = STATE_ON;
1556                 viafb_DVI_ON = STATE_ON;
1557                 viafb_primary_dev = CRT_Device;
1558         } else if (!strncmp(viafb_active_dev, "DVI+CRT", 7)) {
1559                 /* DVI+CRT */
1560                 viafb_CRT_ON = STATE_ON;
1561                 viafb_DVI_ON = STATE_ON;
1562                 viafb_primary_dev = DVI_Device;
1563         } else if (!strncmp(viafb_active_dev, "CRT+LCD", 7)) {
1564                 /* CRT+LCD */
1565                 viafb_CRT_ON = STATE_ON;
1566                 viafb_LCD_ON = STATE_ON;
1567                 viafb_primary_dev = CRT_Device;
1568         } else if (!strncmp(viafb_active_dev, "LCD+CRT", 7)) {
1569                 /* LCD+CRT */
1570                 viafb_CRT_ON = STATE_ON;
1571                 viafb_LCD_ON = STATE_ON;
1572                 viafb_primary_dev = LCD_Device;
1573         } else if (!strncmp(viafb_active_dev, "DVI+LCD", 7)) {
1574                 /* DVI+LCD */
1575                 viafb_DVI_ON = STATE_ON;
1576                 viafb_LCD_ON = STATE_ON;
1577                 viafb_primary_dev = DVI_Device;
1578         } else if (!strncmp(viafb_active_dev, "LCD+DVI", 7)) {
1579                 /* LCD+DVI */
1580                 viafb_DVI_ON = STATE_ON;
1581                 viafb_LCD_ON = STATE_ON;
1582                 viafb_primary_dev = LCD_Device;
1583         } else if (!strncmp(viafb_active_dev, "LCD+LCD2", 8)) {
1584                 viafb_LCD_ON = STATE_ON;
1585                 viafb_LCD2_ON = STATE_ON;
1586                 viafb_primary_dev = LCD_Device;
1587         } else if (!strncmp(viafb_active_dev, "LCD2+LCD", 8)) {
1588                 viafb_LCD_ON = STATE_ON;
1589                 viafb_LCD2_ON = STATE_ON;
1590                 viafb_primary_dev = LCD2_Device;
1591         } else if (!strncmp(viafb_active_dev, "CRT", 3)) {
1592                 /* CRT only */
1593                 viafb_CRT_ON = STATE_ON;
1594                 viafb_SAMM_ON = STATE_OFF;
1595         } else if (!strncmp(viafb_active_dev, "DVI", 3)) {
1596                 /* DVI only */
1597                 viafb_DVI_ON = STATE_ON;
1598                 viafb_SAMM_ON = STATE_OFF;
1599         } else if (!strncmp(viafb_active_dev, "LCD", 3)) {
1600                 /* LCD only */
1601                 viafb_LCD_ON = STATE_ON;
1602                 viafb_SAMM_ON = STATE_OFF;
1603         } else {
1604                 viafb_CRT_ON = STATE_ON;
1605                 viafb_SAMM_ON = STATE_OFF;
1606         }
1607 }
1608
1609 static void parse_video_dev(void)
1610 {
1611         viaparinfo->video_on_crt = STATE_OFF;
1612         viaparinfo->video_on_dvi = STATE_OFF;
1613         viaparinfo->video_on_lcd = STATE_OFF;
1614
1615         if (!strncmp(viafb_video_dev, "CRT", 3)) {
1616                 /* Video on CRT */
1617                 viaparinfo->video_on_crt = STATE_ON;
1618         } else if (!strncmp(viafb_video_dev, "DVI", 3)) {
1619                 /* Video on DVI */
1620                 viaparinfo->video_on_dvi = STATE_ON;
1621         } else if (!strncmp(viafb_video_dev, "LCD", 3)) {
1622                 /* Video on LCD */
1623                 viaparinfo->video_on_lcd = STATE_ON;
1624         }
1625 }
1626
1627 static int parse_port(char *opt_str, int *output_interface)
1628 {
1629         if (!strncmp(opt_str, "DVP0", 4))
1630                 *output_interface = INTERFACE_DVP0;
1631         else if (!strncmp(opt_str, "DVP1", 4))
1632                 *output_interface = INTERFACE_DVP1;
1633         else if (!strncmp(opt_str, "DFP_HIGHLOW", 11))
1634                 *output_interface = INTERFACE_DFP;
1635         else if (!strncmp(opt_str, "DFP_HIGH", 8))
1636                 *output_interface = INTERFACE_DFP_HIGH;
1637         else if (!strncmp(opt_str, "DFP_LOW", 7))
1638                 *output_interface = INTERFACE_DFP_LOW;
1639         else
1640                 *output_interface = INTERFACE_NONE;
1641         return 0;
1642 }
1643
1644 static void parse_lcd_port(void)
1645 {
1646         parse_port(viafb_lcd_port, &viaparinfo->chip_info->lvds_chip_info.
1647                 output_interface);
1648         /*Initialize to avoid unexpected behavior */
1649         viaparinfo->chip_info->lvds_chip_info2.output_interface =
1650         INTERFACE_NONE;
1651
1652         DEBUG_MSG(KERN_INFO "parse_lcd_port: viafb_lcd_port:%s,interface:%d\n",
1653                   viafb_lcd_port, viaparinfo->chip_info->lvds_chip_info.
1654                   output_interface);
1655 }
1656
1657 static void parse_dvi_port(void)
1658 {
1659         parse_port(viafb_dvi_port, &viaparinfo->chip_info->tmds_chip_info.
1660                 output_interface);
1661
1662         DEBUG_MSG(KERN_INFO "parse_dvi_port: viafb_dvi_port:%s,interface:%d\n",
1663                   viafb_dvi_port, viaparinfo->chip_info->tmds_chip_info.
1664                   output_interface);
1665 }
1666
1667 /*
1668  * The proc filesystem read/write function, a simple proc implement to
1669  * get/set the value of DPA  DVP0,   DVP0DataDriving,  DVP0ClockDriving, DVP1,
1670  * DVP1Driving, DFPHigh, DFPLow CR96,   SR2A[5], SR1B[1], SR2A[4], SR1E[2],
1671  * CR9B,    SR65,    CR97,    CR99
1672  */
1673 static int viafb_dvp0_proc_read(char *buf, char **start, off_t offset,
1674 int count, int *eof, void *data)
1675 {
1676         int len = 0;
1677         u8 dvp0_data_dri = 0, dvp0_clk_dri = 0, dvp0 = 0;
1678         dvp0_data_dri =
1679             (viafb_read_reg(VIASR, SR2A) & BIT5) >> 4 |
1680             (viafb_read_reg(VIASR, SR1B) & BIT1) >> 1;
1681         dvp0_clk_dri =
1682             (viafb_read_reg(VIASR, SR2A) & BIT4) >> 3 |
1683             (viafb_read_reg(VIASR, SR1E) & BIT2) >> 2;
1684         dvp0 = viafb_read_reg(VIACR, CR96) & 0x0f;
1685         len +=
1686             sprintf(buf + len, "%x %x %x\n", dvp0, dvp0_data_dri, dvp0_clk_dri);
1687         *eof = 1;               /*Inform kernel end of data */
1688         return len;
1689 }
1690 static int viafb_dvp0_proc_write(struct file *file,
1691         const char __user *buffer, unsigned long count, void *data)
1692 {
1693         char buf[20], *value, *pbuf;
1694         u8 reg_val = 0;
1695         unsigned long length, i;
1696         if (count < 1)
1697                 return -EINVAL;
1698         length = count > 20 ? 20 : count;
1699         if (copy_from_user(&buf[0], buffer, length))
1700                 return -EFAULT;
1701         buf[length - 1] = '\0'; /*Ensure end string */
1702         pbuf = &buf[0];
1703         for (i = 0; i < 3; i++) {
1704                 value = strsep(&pbuf, " ");
1705                 if (value != NULL) {
1706                         strict_strtoul(value, 0, (unsigned long *)&reg_val);
1707                         DEBUG_MSG(KERN_INFO "DVP0:reg_val[%l]=:%x\n", i,
1708                                   reg_val);
1709                         switch (i) {
1710                         case 0:
1711                                 viafb_write_reg_mask(CR96, VIACR,
1712                                         reg_val, 0x0f);
1713                                 break;
1714                         case 1:
1715                                 viafb_write_reg_mask(SR2A, VIASR,
1716                                         reg_val << 4, BIT5);
1717                                 viafb_write_reg_mask(SR1B, VIASR,
1718                                         reg_val << 1, BIT1);
1719                                 break;
1720                         case 2:
1721                                 viafb_write_reg_mask(SR2A, VIASR,
1722                                         reg_val << 3, BIT4);
1723                                 viafb_write_reg_mask(SR1E, VIASR,
1724                                         reg_val << 2, BIT2);
1725                                 break;
1726                         default:
1727                                 break;
1728                         }
1729                 } else {
1730                         break;
1731                 }
1732         }
1733         return count;
1734 }
1735 static int viafb_dvp1_proc_read(char *buf, char **start, off_t offset,
1736         int count, int *eof, void *data)
1737 {
1738         int len = 0;
1739         u8 dvp1 = 0, dvp1_data_dri = 0, dvp1_clk_dri = 0;
1740         dvp1 = viafb_read_reg(VIACR, CR9B) & 0x0f;
1741         dvp1_data_dri = (viafb_read_reg(VIASR, SR65) & 0x0c) >> 2;
1742         dvp1_clk_dri = viafb_read_reg(VIASR, SR65) & 0x03;
1743         len +=
1744             sprintf(buf + len, "%x %x %x\n", dvp1, dvp1_data_dri, dvp1_clk_dri);
1745         *eof = 1;               /*Inform kernel end of data */
1746         return len;
1747 }
1748 static int viafb_dvp1_proc_write(struct file *file,
1749         const char __user *buffer, unsigned long count, void *data)
1750 {
1751         char buf[20], *value, *pbuf;
1752         u8 reg_val = 0;
1753         unsigned long length, i;
1754         if (count < 1)
1755                 return -EINVAL;
1756         length = count > 20 ? 20 : count;
1757         if (copy_from_user(&buf[0], buffer, length))
1758                 return -EFAULT;
1759         buf[length - 1] = '\0'; /*Ensure end string */
1760         pbuf = &buf[0];
1761         for (i = 0; i < 3; i++) {
1762                 value = strsep(&pbuf, " ");
1763                 if (value != NULL) {
1764                         strict_strtoul(value, 0, (unsigned long *)&reg_val);
1765                         switch (i) {
1766                         case 0:
1767                                 viafb_write_reg_mask(CR9B, VIACR,
1768                                         reg_val, 0x0f);
1769                                 break;
1770                         case 1:
1771                                 viafb_write_reg_mask(SR65, VIASR,
1772                                         reg_val << 2, 0x0c);
1773                                 break;
1774                         case 2:
1775                                 viafb_write_reg_mask(SR65, VIASR,
1776                                         reg_val, 0x03);
1777                                 break;
1778                         default:
1779                                 break;
1780                         }
1781                 } else {
1782                         break;
1783                 }
1784         }
1785         return count;
1786 }
1787
1788 static int viafb_dfph_proc_read(char *buf, char **start, off_t offset,
1789         int count, int *eof, void *data)
1790 {
1791         int len = 0;
1792         u8 dfp_high = 0;
1793         dfp_high = viafb_read_reg(VIACR, CR97) & 0x0f;
1794         len += sprintf(buf + len, "%x\n", dfp_high);
1795         *eof = 1;               /*Inform kernel end of data */
1796         return len;
1797 }
1798 static int viafb_dfph_proc_write(struct file *file,
1799         const char __user *buffer, unsigned long count, void *data)
1800 {
1801         char buf[20];
1802         u8 reg_val = 0;
1803         unsigned long length;
1804         if (count < 1)
1805                 return -EINVAL;
1806         length = count > 20 ? 20 : count;
1807         if (copy_from_user(&buf[0], buffer, length))
1808                 return -EFAULT;
1809         buf[length - 1] = '\0'; /*Ensure end string */
1810         strict_strtoul(&buf[0], 0, (unsigned long *)&reg_val);
1811         viafb_write_reg_mask(CR97, VIACR, reg_val, 0x0f);
1812         return count;
1813 }
1814 static int viafb_dfpl_proc_read(char *buf, char **start, off_t offset,
1815         int count, int *eof, void *data)
1816 {
1817         int len = 0;
1818         u8 dfp_low = 0;
1819         dfp_low = viafb_read_reg(VIACR, CR99) & 0x0f;
1820         len += sprintf(buf + len, "%x\n", dfp_low);
1821         *eof = 1;               /*Inform kernel end of data */
1822         return len;
1823 }
1824 static int viafb_dfpl_proc_write(struct file *file,
1825         const char __user *buffer, unsigned long count, void *data)
1826 {
1827         char buf[20];
1828         u8 reg_val = 0;
1829         unsigned long length;
1830         if (count < 1)
1831                 return -EINVAL;
1832         length = count > 20 ? 20 : count;
1833         if (copy_from_user(&buf[0], buffer, length))
1834                 return -EFAULT;
1835         buf[length - 1] = '\0'; /*Ensure end string */
1836         strict_strtoul(&buf[0], 0, (unsigned long *)&reg_val);
1837         viafb_write_reg_mask(CR99, VIACR, reg_val, 0x0f);
1838         return count;
1839 }
1840 static int viafb_vt1636_proc_read(char *buf, char **start,
1841         off_t offset, int count, int *eof, void *data)
1842 {
1843         int len = 0;
1844         u8 vt1636_08 = 0, vt1636_09 = 0;
1845         switch (viaparinfo->chip_info->lvds_chip_info.lvds_chip_name) {
1846         case VT1636_LVDS:
1847                 vt1636_08 =
1848                     viafb_gpio_i2c_read_lvds(viaparinfo->lvds_setting_info,
1849                     &viaparinfo->chip_info->lvds_chip_info, 0x08) & 0x0f;
1850                 vt1636_09 =
1851                     viafb_gpio_i2c_read_lvds(viaparinfo->lvds_setting_info,
1852                     &viaparinfo->chip_info->lvds_chip_info, 0x09) & 0x1f;
1853                 len += sprintf(buf + len, "%x %x\n", vt1636_08, vt1636_09);
1854                 break;
1855         default:
1856                 break;
1857         }
1858         switch (viaparinfo->chip_info->lvds_chip_info2.lvds_chip_name) {
1859         case VT1636_LVDS:
1860                 vt1636_08 =
1861                     viafb_gpio_i2c_read_lvds(viaparinfo->lvds_setting_info2,
1862                         &viaparinfo->chip_info->lvds_chip_info2, 0x08) & 0x0f;
1863                 vt1636_09 =
1864                     viafb_gpio_i2c_read_lvds(viaparinfo->lvds_setting_info2,
1865                         &viaparinfo->chip_info->lvds_chip_info2, 0x09) & 0x1f;
1866                 len += sprintf(buf + len, " %x %x\n", vt1636_08, vt1636_09);
1867                 break;
1868         default:
1869                 break;
1870         }
1871         *eof = 1;               /*Inform kernel end of data */
1872         return len;
1873 }
1874 static int viafb_vt1636_proc_write(struct file *file,
1875         const char __user *buffer, unsigned long count, void *data)
1876 {
1877         char buf[30], *value, *pbuf;
1878         struct IODATA reg_val;
1879         unsigned long length, i;
1880         if (count < 1)
1881                 return -EINVAL;
1882         length = count > 30 ? 30 : count;
1883         if (copy_from_user(&buf[0], buffer, length))
1884                 return -EFAULT;
1885         buf[length - 1] = '\0'; /*Ensure end string */
1886         pbuf = &buf[0];
1887         switch (viaparinfo->chip_info->lvds_chip_info.lvds_chip_name) {
1888         case VT1636_LVDS:
1889                 for (i = 0; i < 2; i++) {
1890                         value = strsep(&pbuf, " ");
1891                         if (value != NULL) {
1892                                 strict_strtoul(value, 0,
1893                                         (unsigned long *)&reg_val.Data);
1894                                 switch (i) {
1895                                 case 0:
1896                                         reg_val.Index = 0x08;
1897                                         reg_val.Mask = 0x0f;
1898                                         viafb_gpio_i2c_write_mask_lvds
1899                                             (viaparinfo->lvds_setting_info,
1900                                             &viaparinfo->
1901                                             chip_info->lvds_chip_info,
1902                                              reg_val);
1903                                         break;
1904                                 case 1:
1905                                         reg_val.Index = 0x09;
1906                                         reg_val.Mask = 0x1f;
1907                                         viafb_gpio_i2c_write_mask_lvds
1908                                             (viaparinfo->lvds_setting_info,
1909                                             &viaparinfo->
1910                                             chip_info->lvds_chip_info,
1911                                              reg_val);
1912                                         break;
1913                                 default:
1914                                         break;
1915                                 }
1916                         } else {
1917                                 break;
1918                         }
1919                 }
1920                 break;
1921         default:
1922                 break;
1923         }
1924         switch (viaparinfo->chip_info->lvds_chip_info2.lvds_chip_name) {
1925         case VT1636_LVDS:
1926                 for (i = 0; i < 2; i++) {
1927                         value = strsep(&pbuf, " ");
1928                         if (value != NULL) {
1929                                 strict_strtoul(value, 0,
1930                                         (unsigned long *)&reg_val.Data);
1931                                 switch (i) {
1932                                 case 0:
1933                                         reg_val.Index = 0x08;
1934                                         reg_val.Mask = 0x0f;
1935                                         viafb_gpio_i2c_write_mask_lvds
1936                                             (viaparinfo->lvds_setting_info2,
1937                                             &viaparinfo->
1938                                             chip_info->lvds_chip_info2,
1939                                              reg_val);
1940                                         break;
1941                                 case 1:
1942                                         reg_val.Index = 0x09;
1943                                         reg_val.Mask = 0x1f;
1944                                         viafb_gpio_i2c_write_mask_lvds
1945                                             (viaparinfo->lvds_setting_info2,
1946                                             &viaparinfo->
1947                                             chip_info->lvds_chip_info2,
1948                                              reg_val);
1949                                         break;
1950                                 default:
1951                                         break;
1952                                 }
1953                         } else {
1954                                 break;
1955                         }
1956                 }
1957                 break;
1958         default:
1959                 break;
1960         }
1961         return count;
1962 }
1963
1964 static void viafb_init_proc(struct proc_dir_entry **viafb_entry)
1965 {
1966         struct proc_dir_entry *entry;
1967         *viafb_entry = proc_mkdir("viafb", NULL);
1968         if (viafb_entry) {
1969                 entry = create_proc_entry("dvp0", 0, *viafb_entry);
1970                 if (entry) {
1971                         entry->read_proc = viafb_dvp0_proc_read;
1972                         entry->write_proc = viafb_dvp0_proc_write;
1973                 }
1974                 entry = create_proc_entry("dvp1", 0, *viafb_entry);
1975                 if (entry) {
1976                         entry->read_proc = viafb_dvp1_proc_read;
1977                         entry->write_proc = viafb_dvp1_proc_write;
1978                 }
1979                 entry = create_proc_entry("dfph", 0, *viafb_entry);
1980                 if (entry) {
1981                         entry->read_proc = viafb_dfph_proc_read;
1982                         entry->write_proc = viafb_dfph_proc_write;
1983                 }
1984                 entry = create_proc_entry("dfpl", 0, *viafb_entry);
1985                 if (entry) {
1986                         entry->read_proc = viafb_dfpl_proc_read;
1987                         entry->write_proc = viafb_dfpl_proc_write;
1988                 }
1989                 if (VT1636_LVDS == viaparinfo->chip_info->lvds_chip_info.
1990                         lvds_chip_name || VT1636_LVDS ==
1991                     viaparinfo->chip_info->lvds_chip_info2.lvds_chip_name) {
1992                         entry = create_proc_entry("vt1636", 0, *viafb_entry);
1993                         if (entry) {
1994                                 entry->read_proc = viafb_vt1636_proc_read;
1995                                 entry->write_proc = viafb_vt1636_proc_write;
1996                         }
1997                 }
1998
1999         }
2000 }
2001 static void viafb_remove_proc(struct proc_dir_entry *viafb_entry)
2002 {
2003         /* no problem if it was not registered */
2004         remove_proc_entry("dvp0", viafb_entry);/* parent dir */
2005         remove_proc_entry("dvp1", viafb_entry);
2006         remove_proc_entry("dfph", viafb_entry);
2007         remove_proc_entry("dfpl", viafb_entry);
2008         remove_proc_entry("vt1636", viafb_entry);
2009         remove_proc_entry("vt1625", viafb_entry);
2010         remove_proc_entry("viafb", NULL);
2011 }
2012
2013 static int __devinit via_pci_probe(void)
2014 {
2015         unsigned long default_xres, default_yres;
2016         char *tmpc, *tmpm;
2017         char *tmpc_sec, *tmpm_sec;
2018         int vmode_index;
2019         u32 tmds_length, lvds_length, crt_length, chip_length, viafb_par_length;
2020
2021         DEBUG_MSG(KERN_INFO "VIAFB PCI Probe!!\n");
2022
2023         viafb_par_length = ALIGN(sizeof(struct viafb_par), BITS_PER_LONG/8);
2024         tmds_length = ALIGN(sizeof(struct tmds_setting_information),
2025                 BITS_PER_LONG/8);
2026         lvds_length = ALIGN(sizeof(struct lvds_setting_information),
2027                 BITS_PER_LONG/8);
2028         crt_length = ALIGN(sizeof(struct lvds_setting_information),
2029                 BITS_PER_LONG/8);
2030         chip_length = ALIGN(sizeof(struct chip_information), BITS_PER_LONG/8);
2031
2032         /* Allocate fb_info and ***_par here, also including some other needed
2033          * variables
2034         */
2035         viafbinfo = framebuffer_alloc(viafb_par_length + 2 * lvds_length +
2036         tmds_length + crt_length + chip_length, NULL);
2037         if (!viafbinfo) {
2038                 printk(KERN_ERR"Could not allocate memory for viafb_info.\n");
2039                 return -ENODEV;
2040         }
2041
2042         viaparinfo = (struct viafb_par *)viafbinfo->par;
2043         viaparinfo->tmds_setting_info = (struct tmds_setting_information *)
2044                 ((unsigned long)viaparinfo + viafb_par_length);
2045         viaparinfo->lvds_setting_info = (struct lvds_setting_information *)
2046                 ((unsigned long)viaparinfo->tmds_setting_info + tmds_length);
2047         viaparinfo->lvds_setting_info2 = (struct lvds_setting_information *)
2048                 ((unsigned long)viaparinfo->lvds_setting_info + lvds_length);
2049         viaparinfo->crt_setting_info = (struct crt_setting_information *)
2050                 ((unsigned long)viaparinfo->lvds_setting_info2 + lvds_length);
2051         viaparinfo->chip_info = (struct chip_information *)
2052                 ((unsigned long)viaparinfo->crt_setting_info + crt_length);
2053
2054         if (viafb_dual_fb)
2055                 viafb_SAMM_ON = 1;
2056         parse_active_dev();
2057         parse_video_dev();
2058         parse_lcd_port();
2059         parse_dvi_port();
2060
2061         /* for dual-fb must viafb_SAMM_ON=1 and viafb_dual_fb=1 */
2062         if (!viafb_SAMM_ON)
2063                 viafb_dual_fb = 0;
2064
2065         /* Set up I2C bus stuff */
2066         viafb_create_i2c_bus(viaparinfo);
2067
2068         viafb_init_chip_info();
2069         viafb_get_fb_info(&viaparinfo->fbmem, &viaparinfo->memsize);
2070         viaparinfo->fbmem_free = viaparinfo->memsize;
2071         viaparinfo->fbmem_used = 0;
2072         viafbinfo->screen_base = ioremap_nocache(viaparinfo->fbmem,
2073                 viaparinfo->memsize);
2074         if (!viafbinfo->screen_base) {
2075                 printk(KERN_INFO "ioremap failed\n");
2076                 return -ENOMEM;
2077         }
2078
2079         viafb_get_mmio_info(&viaparinfo->mmio_base, &viaparinfo->mmio_len);
2080         viaparinfo->io_virt = ioremap_nocache(viaparinfo->mmio_base,
2081                 viaparinfo->mmio_len);
2082         if (!viaparinfo->io_virt) {
2083                 printk(KERN_WARNING "ioremap failed: hardware acceleration disabled\n");
2084                 viafb_accel = 0;
2085         }
2086
2087         viafbinfo->node = 0;
2088         viafbinfo->fbops = &viafb_ops;
2089         viafbinfo->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;
2090
2091         viafbinfo->pseudo_palette = pseudo_pal;
2092         if (viafb_accel) {
2093                 viafb_init_accel();
2094                 viafb_init_2d_engine();
2095                 viafb_hw_cursor_init();
2096         }
2097
2098         if (viafb_second_size && (viafb_second_size < 8)) {
2099                 viafb_second_offset = viaparinfo->fbmem_free -
2100                         viafb_second_size * 1024 * 1024;
2101         } else {
2102                 viafb_second_size = 8;
2103                 viafb_second_offset = viaparinfo->fbmem_free -
2104                         viafb_second_size * 1024 * 1024;
2105         }
2106
2107         tmpm = viafb_mode;
2108         tmpc = strsep(&tmpm, "x");
2109         strict_strtoul(tmpc, 0, &default_xres);
2110         strict_strtoul(tmpm, 0, &default_yres);
2111
2112         vmode_index = viafb_get_mode_index(default_xres, default_yres);
2113         DEBUG_MSG(KERN_INFO "0->index=%d\n", vmode_index);
2114
2115         if (viafb_SAMM_ON == 1) {
2116                 if (strcmp(viafb_mode, viafb_mode1)) {
2117                         tmpm_sec = viafb_mode1;
2118                         tmpc_sec = strsep(&tmpm_sec, "x");
2119                         strict_strtoul(tmpc_sec, 0,
2120                                 (unsigned long *)&viafb_second_xres);
2121                         strict_strtoul(tmpm_sec, 0,
2122                                 (unsigned long *)&viafb_second_yres);
2123                 } else {
2124                         viafb_second_xres = default_xres;
2125                         viafb_second_yres = default_yres;
2126                 }
2127                 if (0 == viafb_second_virtual_xres) {
2128                         switch (viafb_second_xres) {
2129                         case 1400:
2130                                 viafb_second_virtual_xres = 1408;
2131                                 break;
2132                         default:
2133                                 viafb_second_virtual_xres = viafb_second_xres;
2134                                 break;
2135                         }
2136                 }
2137                 if (0 == viafb_second_virtual_yres)
2138                         viafb_second_virtual_yres = viafb_second_yres;
2139         }
2140
2141         switch (viafb_bpp) {
2142         case 0 ... 8:
2143                 viafb_bpp = 8;
2144                 break;
2145         case 9 ... 16:
2146                 viafb_bpp = 16;
2147                 break;
2148         case 17 ... 32:
2149                 viafb_bpp = 32;
2150                 break;
2151         default:
2152                 viafb_bpp = 8;
2153         }
2154         default_var.xres = default_xres;
2155         default_var.yres = default_yres;
2156         switch (default_xres) {
2157         case 1400:
2158                 default_var.xres_virtual = 1408;
2159                 break;
2160         default:
2161                 default_var.xres_virtual = default_xres;
2162                 break;
2163         }
2164         default_var.yres_virtual = default_yres;
2165         default_var.bits_per_pixel = viafb_bpp;
2166         if (default_var.bits_per_pixel == 15)
2167                 default_var.bits_per_pixel = 16;
2168         default_var.pixclock =
2169             viafb_get_pixclock(default_xres, default_yres, viafb_refresh);
2170         default_var.left_margin = (default_xres >> 3) & 0xf8;
2171         default_var.right_margin = 32;
2172         default_var.upper_margin = 16;
2173         default_var.lower_margin = 4;
2174         default_var.hsync_len = default_var.left_margin;
2175         default_var.vsync_len = 4;
2176         default_var.accel_flags = 0;
2177
2178         if (viafb_accel) {
2179                 viafbinfo->flags |=
2180                     (FBINFO_HWACCEL_COPYAREA | FBINFO_HWACCEL_FILLRECT |
2181                      FBINFO_HWACCEL_IMAGEBLIT);
2182                 default_var.accel_flags |= FB_ACCELF_TEXT;
2183         } else
2184                 viafbinfo->flags |= FBINFO_HWACCEL_DISABLED;
2185
2186         if (viafb_dual_fb) {
2187                 viafbinfo1 = framebuffer_alloc(viafb_par_length, NULL);
2188                 if (!viafbinfo1) {
2189                         printk(KERN_ERR
2190                         "allocate the second framebuffer struct error\n");
2191                         framebuffer_release(viafbinfo);
2192                         return -ENOMEM;
2193                 }
2194                 viaparinfo1 = viafbinfo1->par;
2195                 memcpy(viaparinfo1, viaparinfo, viafb_par_length);
2196                 viaparinfo1->memsize = viaparinfo->memsize -
2197                         viafb_second_offset;
2198                 viaparinfo->memsize = viafb_second_offset;
2199                 viaparinfo1->fbmem = viaparinfo->fbmem + viafb_second_offset;
2200
2201                 viaparinfo1->fbmem_used = viaparinfo->fbmem_used;
2202                 viaparinfo1->fbmem_free = viaparinfo1->memsize -
2203                         viaparinfo1->fbmem_used;
2204                 viaparinfo->fbmem_free = viaparinfo->memsize;
2205                 viaparinfo->fbmem_used = 0;
2206                 if (viafb_accel) {
2207                         viaparinfo1->cursor_start =
2208                             viaparinfo->cursor_start - viafb_second_offset;
2209                         viaparinfo1->VQ_start = viaparinfo->VQ_start -
2210                                 viafb_second_offset;
2211                         viaparinfo1->VQ_end = viaparinfo->VQ_end -
2212                                 viafb_second_offset;
2213                 }
2214
2215                 viaparinfo->iga_path = IGA1;
2216                 viaparinfo1->iga_path = IGA2;
2217                 memcpy(viafbinfo1, viafbinfo, sizeof(struct fb_info));
2218                 viafbinfo1->screen_base = viafbinfo->screen_base +
2219                         viafb_second_offset;
2220
2221                 default_var.xres = viafb_second_xres;
2222                 default_var.yres = viafb_second_yres;
2223                 default_var.xres_virtual = viafb_second_virtual_xres;
2224                 default_var.yres_virtual = viafb_second_virtual_yres;
2225                 if (viafb_bpp1 != viafb_bpp)
2226                         viafb_bpp1 = viafb_bpp;
2227                 default_var.bits_per_pixel = viafb_bpp1;
2228                 default_var.pixclock =
2229                     viafb_get_pixclock(viafb_second_xres, viafb_second_yres,
2230                     viafb_refresh);
2231                 default_var.left_margin = (viafb_second_xres >> 3) & 0xf8;
2232                 default_var.right_margin = 32;
2233                 default_var.upper_margin = 16;
2234                 default_var.lower_margin = 4;
2235                 default_var.hsync_len = default_var.left_margin;
2236                 default_var.vsync_len = 4;
2237
2238                 viafb_setup_fixinfo(&viafbinfo1->fix, viaparinfo1);
2239                 viafb_check_var(&default_var, viafbinfo1);
2240                 viafbinfo1->var = default_var;
2241                 viafb_update_fix(viafbinfo1);
2242         }
2243
2244         viafb_setup_fixinfo(&viafbinfo->fix, viaparinfo);
2245         viafb_check_var(&default_var, viafbinfo);
2246         viafbinfo->var = default_var;
2247         viafb_update_fix(viafbinfo);
2248         default_var.activate = FB_ACTIVATE_NOW;
2249         fb_alloc_cmap(&viafbinfo->cmap, 256, 0);
2250
2251         if (viafb_dual_fb && (viafb_primary_dev == LCD_Device)
2252             && (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266)) {
2253                 if (register_framebuffer(viafbinfo1) < 0)
2254                         return -EINVAL;
2255         }
2256         if (register_framebuffer(viafbinfo) < 0)
2257                 return -EINVAL;
2258
2259         if (viafb_dual_fb && ((viafb_primary_dev != LCD_Device)
2260                         || (viaparinfo->chip_info->gfx_chip_name !=
2261                         UNICHROME_CLE266))) {
2262                 if (register_framebuffer(viafbinfo1) < 0)
2263                         return -EINVAL;
2264         }
2265         DEBUG_MSG(KERN_INFO "fb%d: %s frame buffer device %dx%d-%dbpp\n",
2266                   viafbinfo->node, viafbinfo->fix.id, default_var.xres,
2267                   default_var.yres, default_var.bits_per_pixel);
2268
2269         viafb_init_proc(&viaparinfo->proc_entry);
2270         viafb_init_dac(IGA2);
2271         return 0;
2272 }
2273
2274 static void __devexit via_pci_remove(void)
2275 {
2276         DEBUG_MSG(KERN_INFO "via_pci_remove!\n");
2277         fb_dealloc_cmap(&viafbinfo->cmap);
2278         unregister_framebuffer(viafbinfo);
2279         if (viafb_dual_fb)
2280                 unregister_framebuffer(viafbinfo1);
2281         iounmap((void *)viafbinfo->screen_base);
2282         iounmap(viaparinfo->io_virt);
2283
2284         viafb_delete_i2c_buss(viaparinfo);
2285
2286         framebuffer_release(viafbinfo);
2287         if (viafb_dual_fb)
2288                 framebuffer_release(viafbinfo1);
2289
2290         viafb_remove_proc(viaparinfo->proc_entry);
2291 }
2292
2293 #ifndef MODULE
2294 static int __init viafb_setup(char *options)
2295 {
2296         char *this_opt;
2297         DEBUG_MSG(KERN_INFO "viafb_setup!\n");
2298
2299         if (!options || !*options)
2300                 return 0;
2301
2302         while ((this_opt = strsep(&options, ",")) != NULL) {
2303                 if (!*this_opt)
2304                         continue;
2305
2306                 if (!strncmp(this_opt, "viafb_mode1=", 12))
2307                         viafb_mode1 = kstrdup(this_opt + 12, GFP_KERNEL);
2308                 else if (!strncmp(this_opt, "viafb_mode=", 11))
2309                         viafb_mode = kstrdup(this_opt + 11, GFP_KERNEL);
2310                 else if (!strncmp(this_opt, "viafb_bpp1=", 11))
2311                         strict_strtoul(this_opt + 11, 0,
2312                                 (unsigned long *)&viafb_bpp1);
2313                 else if (!strncmp(this_opt, "viafb_bpp=", 10))
2314                         strict_strtoul(this_opt + 10, 0,
2315                                 (unsigned long *)&viafb_bpp);
2316                 else if (!strncmp(this_opt, "viafb_refresh1=", 15))
2317                         strict_strtoul(this_opt + 15, 0,
2318                                 (unsigned long *)&viafb_refresh1);
2319                 else if (!strncmp(this_opt, "viafb_refresh=", 14))
2320                         strict_strtoul(this_opt + 14, 0,
2321                                 (unsigned long *)&viafb_refresh);
2322                 else if (!strncmp(this_opt, "viafb_lcd_dsp_method=", 21))
2323                         strict_strtoul(this_opt + 21, 0,
2324                                 (unsigned long *)&viafb_lcd_dsp_method);
2325                 else if (!strncmp(this_opt, "viafb_lcd_panel_id=", 19))
2326                         strict_strtoul(this_opt + 19, 0,
2327                                 (unsigned long *)&viafb_lcd_panel_id);
2328                 else if (!strncmp(this_opt, "viafb_accel=", 12))
2329                         strict_strtoul(this_opt + 12, 0,
2330                                 (unsigned long *)&viafb_accel);
2331                 else if (!strncmp(this_opt, "viafb_SAMM_ON=", 14))
2332                         strict_strtoul(this_opt + 14, 0,
2333                                 (unsigned long *)&viafb_SAMM_ON);
2334                 else if (!strncmp(this_opt, "viafb_active_dev=", 17))
2335                         viafb_active_dev = kstrdup(this_opt + 17, GFP_KERNEL);
2336                 else if (!strncmp(this_opt,
2337                         "viafb_display_hardware_layout=", 30))
2338                         strict_strtoul(this_opt + 30, 0,
2339                         (unsigned long *)&viafb_display_hardware_layout);
2340                 else if (!strncmp(this_opt, "viafb_second_size=", 18))
2341                         strict_strtoul(this_opt + 18, 0,
2342                                 (unsigned long *)&viafb_second_size);
2343                 else if (!strncmp(this_opt,
2344                         "viafb_platform_epia_dvi=", 24))
2345                         strict_strtoul(this_opt + 24, 0,
2346                                 (unsigned long *)&viafb_platform_epia_dvi);
2347                 else if (!strncmp(this_opt,
2348                         "viafb_device_lcd_dualedge=", 26))
2349                         strict_strtoul(this_opt + 26, 0,
2350                                 (unsigned long *)&viafb_device_lcd_dualedge);
2351                 else if (!strncmp(this_opt, "viafb_bus_width=", 16))
2352                         strict_strtoul(this_opt + 16, 0,
2353                                 (unsigned long *)&viafb_bus_width);
2354                 else if (!strncmp(this_opt, "viafb_lcd_mode=", 15))
2355                         strict_strtoul(this_opt + 15, 0,
2356                                 (unsigned long *)&viafb_lcd_mode);
2357                 else if (!strncmp(this_opt, "viafb_video_dev=", 16))
2358                         viafb_video_dev = kstrdup(this_opt + 16, GFP_KERNEL);
2359                 else if (!strncmp(this_opt, "viafb_lcd_port=", 15))
2360                         viafb_lcd_port = kstrdup(this_opt + 15, GFP_KERNEL);
2361                 else if (!strncmp(this_opt, "viafb_dvi_port=", 15))
2362                         viafb_dvi_port = kstrdup(this_opt + 15, GFP_KERNEL);
2363         }
2364         return 0;
2365 }
2366 #endif
2367
2368 static int __init viafb_init(void)
2369 {
2370 #ifndef MODULE
2371         char *option = NULL;
2372         if (fb_get_options("viafb", &option))
2373                 return -ENODEV;
2374         viafb_setup(option);
2375 #endif
2376         printk(KERN_INFO
2377        "VIA Graphics Intergration Chipset framebuffer %d.%d initializing\n",
2378                VERSION_MAJOR, VERSION_MINOR);
2379         return via_pci_probe();
2380 }
2381
2382 static void __exit viafb_exit(void)
2383 {
2384         DEBUG_MSG(KERN_INFO "viafb_exit!\n");
2385         via_pci_remove();
2386 }
2387
2388 static struct fb_ops viafb_ops = {
2389         .owner = THIS_MODULE,
2390         .fb_open = viafb_open,
2391         .fb_release = viafb_release,
2392         .fb_check_var = viafb_check_var,
2393         .fb_set_par = viafb_set_par,
2394         .fb_setcolreg = viafb_setcolreg,
2395         .fb_pan_display = viafb_pan_display,
2396         .fb_blank = viafb_blank,
2397         .fb_fillrect = viafb_fillrect,
2398         .fb_copyarea = viafb_copyarea,
2399         .fb_imageblit = viafb_imageblit,
2400         .fb_cursor = viafb_cursor,
2401         .fb_ioctl = viafb_ioctl,
2402         .fb_sync = viafb_sync,
2403         .fb_setcmap = viafb_setcmap,
2404 };
2405
2406 module_init(viafb_init);
2407 module_exit(viafb_exit);
2408
2409 #ifdef MODULE
2410 module_param(viafb_memsize, int, 0);
2411
2412 module_param(viafb_mode, charp, 0);
2413 MODULE_PARM_DESC(viafb_mode, "Set resolution (default=640x480)");
2414
2415 module_param(viafb_mode1, charp, 0);
2416 MODULE_PARM_DESC(viafb_mode1, "Set resolution (default=640x480)");
2417
2418 module_param(viafb_bpp, int, 0);
2419 MODULE_PARM_DESC(viafb_bpp, "Set color depth (default=32bpp)");
2420
2421 module_param(viafb_bpp1, int, 0);
2422 MODULE_PARM_DESC(viafb_bpp1, "Set color depth (default=32bpp)");
2423
2424 module_param(viafb_refresh, int, 0);
2425 MODULE_PARM_DESC(viafb_refresh,
2426         "Set CRT viafb_refresh rate (default = 60)");
2427
2428 module_param(viafb_refresh1, int, 0);
2429 MODULE_PARM_DESC(viafb_refresh1,
2430         "Set CRT refresh rate (default = 60)");
2431
2432 module_param(viafb_lcd_panel_id, int, 0);
2433 MODULE_PARM_DESC(viafb_lcd_panel_id,
2434         "Set Flat Panel type(Default=1024x768)");
2435
2436 module_param(viafb_lcd_dsp_method, int, 0);
2437 MODULE_PARM_DESC(viafb_lcd_dsp_method,
2438         "Set Flat Panel display scaling method.(Default=Expandsion)");
2439
2440 module_param(viafb_SAMM_ON, int, 0);
2441 MODULE_PARM_DESC(viafb_SAMM_ON,
2442         "Turn on/off flag of SAMM(Default=OFF)");
2443
2444 module_param(viafb_accel, int, 0);
2445 MODULE_PARM_DESC(viafb_accel,
2446         "Set 2D Hardware Acceleration.(Default = OFF)");
2447
2448 module_param(viafb_active_dev, charp, 0);
2449 MODULE_PARM_DESC(viafb_active_dev, "Specify active devices.");
2450
2451 module_param(viafb_display_hardware_layout, int, 0);
2452 MODULE_PARM_DESC(viafb_display_hardware_layout,
2453         "Display Hardware Layout (LCD Only, DVI Only...,etc)");
2454
2455 module_param(viafb_second_size, int, 0);
2456 MODULE_PARM_DESC(viafb_second_size,
2457         "Set secondary device memory size");
2458
2459 module_param(viafb_dual_fb, int, 0);
2460 MODULE_PARM_DESC(viafb_dual_fb,
2461         "Turn on/off flag of dual framebuffer devices.(Default = OFF)");
2462
2463 module_param(viafb_platform_epia_dvi, int, 0);
2464 MODULE_PARM_DESC(viafb_platform_epia_dvi,
2465         "Turn on/off flag of DVI devices on EPIA board.(Default = OFF)");
2466
2467 module_param(viafb_device_lcd_dualedge, int, 0);
2468 MODULE_PARM_DESC(viafb_device_lcd_dualedge,
2469         "Turn on/off flag of dual edge panel.(Default = OFF)");
2470
2471 module_param(viafb_bus_width, int, 0);
2472 MODULE_PARM_DESC(viafb_bus_width,
2473         "Set bus width of panel.(Default = 12)");
2474
2475 module_param(viafb_lcd_mode, int, 0);
2476 MODULE_PARM_DESC(viafb_lcd_mode,
2477         "Set Flat Panel mode(Default=OPENLDI)");
2478
2479 module_param(viafb_video_dev, charp, 0);
2480 MODULE_PARM_DESC(viafb_video_dev, "Specify video devices.");
2481
2482 module_param(viafb_lcd_port, charp, 0);
2483 MODULE_PARM_DESC(viafb_lcd_port, "Specify LCD output port.");
2484
2485 module_param(viafb_dvi_port, charp, 0);
2486 MODULE_PARM_DESC(viafb_dvi_port, "Specify DVI output port.");
2487
2488 MODULE_LICENSE("GPL");
2489 #endif