aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video/via/viafbdev.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/video/via/viafbdev.c')
-rw-r--r--drivers/video/via/viafbdev.c530
1 files changed, 203 insertions, 327 deletions
diff --git a/drivers/video/via/viafbdev.c b/drivers/video/via/viafbdev.c
index 56ec696e8afa..777b38a06d40 100644
--- a/drivers/video/via/viafbdev.c
+++ b/drivers/video/via/viafbdev.c
@@ -21,23 +21,28 @@
21 21
22#include <linux/module.h> 22#include <linux/module.h>
23#include <linux/seq_file.h> 23#include <linux/seq_file.h>
24#include <linux/slab.h>
24#include <linux/stat.h> 25#include <linux/stat.h>
25#define _MASTER_FILE 26#define _MASTER_FILE
26 27
27#include "global.h" 28#include "global.h"
28 29
29static struct fb_var_screeninfo default_var;
30static char *viafb_name = "Via"; 30static char *viafb_name = "Via";
31static u32 pseudo_pal[17]; 31static u32 pseudo_pal[17];
32 32
33/* video mode */ 33/* video mode */
34static char *viafb_mode = "640x480"; 34static char *viafb_mode;
35static char *viafb_mode1 = "640x480"; 35static char *viafb_mode1;
36static int viafb_bpp = 32;
37static int viafb_bpp1 = 32;
38
39static unsigned int viafb_second_offset;
40static int viafb_second_size;
36 41
37static int viafb_accel = 1; 42static int viafb_accel = 1;
38 43
39/* Added for specifying active devices.*/ 44/* Added for specifying active devices.*/
40char *viafb_active_dev = ""; 45char *viafb_active_dev;
41 46
42/*Added for specify lcd output port*/ 47/*Added for specify lcd output port*/
43char *viafb_lcd_port = ""; 48char *viafb_lcd_port = "";
@@ -50,18 +55,78 @@ static void apply_second_mode_setting(struct fb_var_screeninfo
50 *sec_var); 55 *sec_var);
51static void retrieve_device_setting(struct viafb_ioctl_setting 56static void retrieve_device_setting(struct viafb_ioctl_setting
52 *setting_info); 57 *setting_info);
58static int viafb_pan_display(struct fb_var_screeninfo *var,
59 struct fb_info *info);
53 60
54static struct fb_ops viafb_ops; 61static struct fb_ops viafb_ops;
55 62
56 63
64static void viafb_fill_var_color_info(struct fb_var_screeninfo *var, u8 depth)
65{
66 var->grayscale = 0;
67 var->red.msb_right = 0;
68 var->green.msb_right = 0;
69 var->blue.msb_right = 0;
70 var->transp.offset = 0;
71 var->transp.length = 0;
72 var->transp.msb_right = 0;
73 var->nonstd = 0;
74 switch (depth) {
75 case 8:
76 var->bits_per_pixel = 8;
77 var->red.offset = 0;
78 var->green.offset = 0;
79 var->blue.offset = 0;
80 var->red.length = 8;
81 var->green.length = 8;
82 var->blue.length = 8;
83 break;
84 case 15:
85 var->bits_per_pixel = 16;
86 var->red.offset = 10;
87 var->green.offset = 5;
88 var->blue.offset = 0;
89 var->red.length = 5;
90 var->green.length = 5;
91 var->blue.length = 5;
92 break;
93 case 16:
94 var->bits_per_pixel = 16;
95 var->red.offset = 11;
96 var->green.offset = 5;
97 var->blue.offset = 0;
98 var->red.length = 5;
99 var->green.length = 6;
100 var->blue.length = 5;
101 break;
102 case 24:
103 var->bits_per_pixel = 32;
104 var->red.offset = 16;
105 var->green.offset = 8;
106 var->blue.offset = 0;
107 var->red.length = 8;
108 var->green.length = 8;
109 var->blue.length = 8;
110 break;
111 case 30:
112 var->bits_per_pixel = 32;
113 var->red.offset = 20;
114 var->green.offset = 10;
115 var->blue.offset = 0;
116 var->red.length = 10;
117 var->green.length = 10;
118 var->blue.length = 10;
119 break;
120 }
121}
122
57static void viafb_update_fix(struct fb_info *info) 123static void viafb_update_fix(struct fb_info *info)
58{ 124{
59 u32 bpp = info->var.bits_per_pixel; 125 u32 bpp = info->var.bits_per_pixel;
60 126
61 info->fix.visual = 127 info->fix.visual =
62 bpp == 8 ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR; 128 bpp == 8 ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR;
63 info->fix.line_length = 129 info->fix.line_length = (info->var.xres_virtual * bpp / 8 + 7) & ~7;
64 ((info->var.xres_virtual + 7) & ~7) * bpp / 8;
65} 130}
66 131
67static void viafb_setup_fixinfo(struct fb_fix_screeninfo *fix, 132static void viafb_setup_fixinfo(struct fb_fix_screeninfo *fix,
@@ -75,6 +140,7 @@ static void viafb_setup_fixinfo(struct fb_fix_screeninfo *fix,
75 140
76 fix->type = FB_TYPE_PACKED_PIXELS; 141 fix->type = FB_TYPE_PACKED_PIXELS;
77 fix->type_aux = 0; 142 fix->type_aux = 0;
143 fix->visual = FB_VISUAL_TRUECOLOR;
78 144
79 fix->xpanstep = fix->ywrapstep = 0; 145 fix->xpanstep = fix->ywrapstep = 0;
80 fix->ypanstep = 1; 146 fix->ypanstep = 1;
@@ -97,9 +163,10 @@ static int viafb_release(struct fb_info *info, int user)
97static int viafb_check_var(struct fb_var_screeninfo *var, 163static int viafb_check_var(struct fb_var_screeninfo *var,
98 struct fb_info *info) 164 struct fb_info *info)
99{ 165{
100 int vmode_index, htotal, vtotal; 166 int htotal, vtotal, depth;
167 struct VideoModeTable *vmode_entry;
101 struct viafb_par *ppar = info->par; 168 struct viafb_par *ppar = info->par;
102 u32 long_refresh; 169 u32 long_refresh, line;
103 170
104 DEBUG_MSG(KERN_INFO "viafb_check_var!\n"); 171 DEBUG_MSG(KERN_INFO "viafb_check_var!\n");
105 /* Sanity check */ 172 /* Sanity check */
@@ -107,26 +174,36 @@ static int viafb_check_var(struct fb_var_screeninfo *var,
107 if (var->vmode & FB_VMODE_INTERLACED || var->vmode & FB_VMODE_DOUBLE) 174 if (var->vmode & FB_VMODE_INTERLACED || var->vmode & FB_VMODE_DOUBLE)
108 return -EINVAL; 175 return -EINVAL;
109 176
110 vmode_index = viafb_get_mode_index(var->xres, var->yres); 177 vmode_entry = viafb_get_mode(var->xres, var->yres);
111 if (vmode_index == VIA_RES_INVALID) { 178 if (!vmode_entry) {
112 DEBUG_MSG(KERN_INFO 179 DEBUG_MSG(KERN_INFO
113 "viafb: Mode %dx%dx%d not supported!!\n", 180 "viafb: Mode %dx%dx%d not supported!!\n",
114 var->xres, var->yres, var->bits_per_pixel); 181 var->xres, var->yres, var->bits_per_pixel);
115 return -EINVAL; 182 return -EINVAL;
116 } 183 }
117 184
118 if (24 == var->bits_per_pixel) 185 depth = fb_get_color_depth(var, &info->fix);
119 var->bits_per_pixel = 32; 186 if (!depth)
187 depth = var->bits_per_pixel;
120 188
121 if (var->bits_per_pixel != 8 && var->bits_per_pixel != 16 && 189 if (depth < 0 || depth > 32)
122 var->bits_per_pixel != 32)
123 return -EINVAL; 190 return -EINVAL;
191 else if (!depth)
192 depth = 24;
193 else if (depth == 15 && viafb_dual_fb && ppar->iga_path == IGA1)
194 depth = 15;
195 else if (depth == 30)
196 depth = 30;
197 else if (depth <= 8)
198 depth = 8;
199 else if (depth <= 16)
200 depth = 16;
201 else
202 depth = 24;
124 203
125 if ((var->xres_virtual * (var->bits_per_pixel >> 3)) & 0x1F) 204 viafb_fill_var_color_info(var, depth);
126 /*32 pixel alignment */ 205 line = (var->xres_virtual * var->bits_per_pixel / 8 + 7) & ~7;
127 var->xres_virtual = (var->xres_virtual + 31) & ~31; 206 if (line * var->yres_virtual > ppar->memsize)
128 if (var->xres_virtual * var->yres_virtual * var->bits_per_pixel / 8 >
129 ppar->memsize)
130 return -EINVAL; 207 return -EINVAL;
131 208
132 /* Based on var passed in to calculate the refresh, 209 /* Based on var passed in to calculate the refresh,
@@ -142,7 +219,7 @@ static int viafb_check_var(struct fb_var_screeninfo *var,
142 viafb_refresh = viafb_get_refresh(var->xres, var->yres, long_refresh); 219 viafb_refresh = viafb_get_refresh(var->xres, var->yres, long_refresh);
143 220
144 /* Adjust var according to our driver's own table */ 221 /* Adjust var according to our driver's own table */
145 viafb_fill_var_timing_info(var, viafb_refresh, vmode_index); 222 viafb_fill_var_timing_info(var, viafb_refresh, vmode_entry);
146 if (info->var.accel_flags & FB_ACCELF_TEXT && 223 if (info->var.accel_flags & FB_ACCELF_TEXT &&
147 !ppar->shared->engine_mmio) 224 !ppar->shared->engine_mmio)
148 info->var.accel_flags = 0; 225 info->var.accel_flags = 0;
@@ -153,40 +230,45 @@ static int viafb_check_var(struct fb_var_screeninfo *var,
153static int viafb_set_par(struct fb_info *info) 230static int viafb_set_par(struct fb_info *info)
154{ 231{
155 struct viafb_par *viapar = info->par; 232 struct viafb_par *viapar = info->par;
156 int vmode_index; 233 struct VideoModeTable *vmode_entry, *vmode_entry1 = NULL;
157 int vmode_index1 = 0;
158 DEBUG_MSG(KERN_INFO "viafb_set_par!\n"); 234 DEBUG_MSG(KERN_INFO "viafb_set_par!\n");
159 235
160 viapar->depth = fb_get_color_depth(&info->var, &info->fix); 236 viapar->depth = fb_get_color_depth(&info->var, &info->fix);
161 viafb_update_device_setting(info->var.xres, info->var.yres, 237 viafb_update_device_setting(viafbinfo->var.xres, viafbinfo->var.yres,
162 info->var.bits_per_pixel, viafb_refresh, 0); 238 viafbinfo->var.bits_per_pixel, viafb_refresh, 0);
163 239
164 vmode_index = viafb_get_mode_index(info->var.xres, info->var.yres); 240 vmode_entry = viafb_get_mode(viafbinfo->var.xres, viafbinfo->var.yres);
165 241 if (viafb_dual_fb) {
166 if (viafb_SAMM_ON == 1) { 242 vmode_entry1 = viafb_get_mode(viafbinfo1->var.xres,
243 viafbinfo1->var.yres);
244 viafb_update_device_setting(viafbinfo1->var.xres,
245 viafbinfo1->var.yres, viafbinfo1->var.bits_per_pixel,
246 viafb_refresh1, 1);
247 } else if (viafb_SAMM_ON == 1) {
167 DEBUG_MSG(KERN_INFO 248 DEBUG_MSG(KERN_INFO
168 "viafb_second_xres = %d, viafb_second_yres = %d, bpp = %d\n", 249 "viafb_second_xres = %d, viafb_second_yres = %d, bpp = %d\n",
169 viafb_second_xres, viafb_second_yres, viafb_bpp1); 250 viafb_second_xres, viafb_second_yres, viafb_bpp1);
170 vmode_index1 = viafb_get_mode_index(viafb_second_xres, 251 vmode_entry1 = viafb_get_mode(viafb_second_xres,
171 viafb_second_yres); 252 viafb_second_yres);
172 DEBUG_MSG(KERN_INFO "->viafb_SAMM_ON: index=%d\n",
173 vmode_index1);
174 253
175 viafb_update_device_setting(viafb_second_xres, 254 viafb_update_device_setting(viafb_second_xres,
176 viafb_second_yres, viafb_bpp1, viafb_refresh1, 1); 255 viafb_second_yres, viafb_bpp1, viafb_refresh1, 1);
177 } 256 }
178 257
179 if (vmode_index != VIA_RES_INVALID) { 258 if (vmode_entry) {
180 viafb_setmode(vmode_index, info->var.xres, info->var.yres,
181 info->var.bits_per_pixel, vmode_index1,
182 viafb_second_xres, viafb_second_yres, viafb_bpp1);
183
184 viafb_update_fix(info); 259 viafb_update_fix(info);
185 viafb_bpp = info->var.bits_per_pixel; 260 if (viafb_dual_fb && viapar->iga_path == IGA2)
261 viafb_bpp1 = info->var.bits_per_pixel;
262 else
263 viafb_bpp = info->var.bits_per_pixel;
264
186 if (info->var.accel_flags & FB_ACCELF_TEXT) 265 if (info->var.accel_flags & FB_ACCELF_TEXT)
187 info->flags &= ~FBINFO_HWACCEL_DISABLED; 266 info->flags &= ~FBINFO_HWACCEL_DISABLED;
188 else 267 else
189 info->flags |= FBINFO_HWACCEL_DISABLED; 268 info->flags |= FBINFO_HWACCEL_DISABLED;
269 viafb_setmode(vmode_entry, info->var.bits_per_pixel,
270 vmode_entry1, viafb_bpp1);
271 viafb_pan_display(&info->var, info);
190 } 272 }
191 273
192 return 0; 274 return 0;
@@ -196,234 +278,52 @@ static int viafb_set_par(struct fb_info *info)
196static int viafb_setcolreg(unsigned regno, unsigned red, unsigned green, 278static int viafb_setcolreg(unsigned regno, unsigned red, unsigned green,
197unsigned blue, unsigned transp, struct fb_info *info) 279unsigned blue, unsigned transp, struct fb_info *info)
198{ 280{
199 u8 sr1a, sr1b, cr67, cr6a, rev = 0, shift = 10; 281 struct viafb_par *viapar = info->par;
200 unsigned cmap_entries = (info->var.bits_per_pixel == 8) ? 256 : 16; 282 u32 r, g, b;
201 DEBUG_MSG(KERN_INFO "viafb_setcolreg!\n");
202 if (regno >= cmap_entries)
203 return 1;
204 if (UNICHROME_CLE266 == viaparinfo->chip_info->gfx_chip_name) {
205 /*
206 * Read PCI bus 0,dev 0,function 0,index 0xF6 to get chip rev.
207 */
208 outl(0x80000000 | (0xf6 & ~3), (unsigned long)0xCF8);
209 rev = (inl((unsigned long)0xCFC) >> ((0xf6 & 3) * 8)) & 0xff;
210 }
211 switch (info->var.bits_per_pixel) {
212 case 8:
213 outb(0x1A, 0x3C4);
214 sr1a = inb(0x3C5);
215 outb(0x1B, 0x3C4);
216 sr1b = inb(0x3C5);
217 outb(0x67, 0x3D4);
218 cr67 = inb(0x3D5);
219 outb(0x6A, 0x3D4);
220 cr6a = inb(0x3D5);
221
222 /* Map the 3C6/7/8/9 to the IGA2 */
223 outb(0x1A, 0x3C4);
224 outb(sr1a | 0x01, 0x3C5);
225 /* Second Display Engine colck always on */
226 outb(0x1B, 0x3C4);
227 outb(sr1b | 0x80, 0x3C5);
228 /* Second Display Color Depth 8 */
229 outb(0x67, 0x3D4);
230 outb(cr67 & 0x3F, 0x3D5);
231 outb(0x6A, 0x3D4);
232 /* Second Display Channel Reset CR6A[6]) */
233 outb(cr6a & 0xBF, 0x3D5);
234 /* Second Display Channel Enable CR6A[7] */
235 outb(cr6a | 0x80, 0x3D5);
236 /* Second Display Channel stop reset) */
237 outb(cr6a | 0x40, 0x3D5);
238
239 /* Bit mask of palette */
240 outb(0xFF, 0x3c6);
241 /* Write one register of IGA2 */
242 outb(regno, 0x3C8);
243 if (UNICHROME_CLE266 == viaparinfo->chip_info->gfx_chip_name &&
244 rev >= 15) {
245 shift = 8;
246 viafb_write_reg_mask(CR6A, VIACR, BIT5, BIT5);
247 viafb_write_reg_mask(SR15, VIASR, BIT7, BIT7);
248 } else {
249 shift = 10;
250 viafb_write_reg_mask(CR6A, VIACR, 0, BIT5);
251 viafb_write_reg_mask(SR15, VIASR, 0, BIT7);
252 }
253 outb(red >> shift, 0x3C9);
254 outb(green >> shift, 0x3C9);
255 outb(blue >> shift, 0x3C9);
256
257 /* Map the 3C6/7/8/9 to the IGA1 */
258 outb(0x1A, 0x3C4);
259 outb(sr1a & 0xFE, 0x3C5);
260 /* Bit mask of palette */
261 outb(0xFF, 0x3c6);
262 /* Write one register of IGA1 */
263 outb(regno, 0x3C8);
264 outb(red >> shift, 0x3C9);
265 outb(green >> shift, 0x3C9);
266 outb(blue >> shift, 0x3C9);
267
268 outb(0x1A, 0x3C4);
269 outb(sr1a, 0x3C5);
270 outb(0x1B, 0x3C4);
271 outb(sr1b, 0x3C5);
272 outb(0x67, 0x3D4);
273 outb(cr67, 0x3D5);
274 outb(0x6A, 0x3D4);
275 outb(cr6a, 0x3D5);
276 break;
277 case 16:
278 ((u32 *) info->pseudo_palette)[regno] = (red & 0xF800) |
279 ((green & 0xFC00) >> 5) | ((blue & 0xF800) >> 11);
280 break;
281 case 32:
282 ((u32 *) info->pseudo_palette)[regno] =
283 ((transp & 0xFF00) << 16) |
284 ((red & 0xFF00) << 8) |
285 ((green & 0xFF00)) | ((blue & 0xFF00) >> 8);
286 break;
287 }
288
289 return 0;
290 283
291} 284 if (info->fix.visual == FB_VISUAL_PSEUDOCOLOR) {
285 if (regno > 255)
286 return -EINVAL;
292 287
293/*CALLED BY: fb_set_cmap */ 288 if (!viafb_dual_fb || viapar->iga_path == IGA1)
294/* fb_set_var, pass 256 colors */ 289 viafb_set_primary_color_register(regno, red >> 8,
295/*CALLED BY: fb_set_cmap */ 290 green >> 8, blue >> 8);
296/* fbcon_set_palette, pass 16 colors */
297static int viafb_setcmap(struct fb_cmap *cmap, struct fb_info *info)
298{
299 u32 len = cmap->len;
300 u32 i;
301 u16 *pred = cmap->red;
302 u16 *pgreen = cmap->green;
303 u16 *pblue = cmap->blue;
304 u16 *ptransp = cmap->transp;
305 u8 sr1a, sr1b, cr67, cr6a, rev = 0, shift = 10;
306 if (len > 256)
307 return 1;
308 if (UNICHROME_CLE266 == viaparinfo->chip_info->gfx_chip_name) {
309 /*
310 * Read PCI bus 0, dev 0, function 0, index 0xF6 to get chip
311 * rev.
312 */
313 outl(0x80000000 | (0xf6 & ~3), (unsigned long)0xCF8);
314 rev = (inl((unsigned long)0xCFC) >> ((0xf6 & 3) * 8)) & 0xff;
315 }
316 switch (info->var.bits_per_pixel) {
317 case 8:
318 outb(0x1A, 0x3C4);
319 sr1a = inb(0x3C5);
320 outb(0x1B, 0x3C4);
321 sr1b = inb(0x3C5);
322 outb(0x67, 0x3D4);
323 cr67 = inb(0x3D5);
324 outb(0x6A, 0x3D4);
325 cr6a = inb(0x3D5);
326 /* Map the 3C6/7/8/9 to the IGA2 */
327 outb(0x1A, 0x3C4);
328 outb(sr1a | 0x01, 0x3C5);
329 outb(0x1B, 0x3C4);
330 /* Second Display Engine colck always on */
331 outb(sr1b | 0x80, 0x3C5);
332 outb(0x67, 0x3D4);
333 /* Second Display Color Depth 8 */
334 outb(cr67 & 0x3F, 0x3D5);
335 outb(0x6A, 0x3D4);
336 /* Second Display Channel Reset CR6A[6]) */
337 outb(cr6a & 0xBF, 0x3D5);
338 /* Second Display Channel Enable CR6A[7] */
339 outb(cr6a | 0x80, 0x3D5);
340 /* Second Display Channel stop reset) */
341 outb(cr6a | 0xC0, 0x3D5);
342
343 /* Bit mask of palette */
344 outb(0xFF, 0x3c6);
345 outb(0x00, 0x3C8);
346 if (UNICHROME_CLE266 == viaparinfo->chip_info->gfx_chip_name &&
347 rev >= 15) {
348 shift = 8;
349 viafb_write_reg_mask(CR6A, VIACR, BIT5, BIT5);
350 viafb_write_reg_mask(SR15, VIASR, BIT7, BIT7);
351 } else {
352 shift = 10;
353 viafb_write_reg_mask(CR6A, VIACR, 0, BIT5);
354 viafb_write_reg_mask(SR15, VIASR, 0, BIT7);
355 }
356 for (i = 0; i < len; i++) {
357 outb((*(pred + i)) >> shift, 0x3C9);
358 outb((*(pgreen + i)) >> shift, 0x3C9);
359 outb((*(pblue + i)) >> shift, 0x3C9);
360 }
361 291
362 outb(0x1A, 0x3C4); 292 if (!viafb_dual_fb || viapar->iga_path == IGA2)
363 /* Map the 3C6/7/8/9 to the IGA1 */ 293 viafb_set_secondary_color_register(regno, red >> 8,
364 outb(sr1a & 0xFE, 0x3C5); 294 green >> 8, blue >> 8);
365 /* Bit mask of palette */ 295 } else {
366 outb(0xFF, 0x3c6); 296 if (regno > 15)
367 outb(0x00, 0x3C8); 297 return -EINVAL;
368 for (i = 0; i < len; i++) {
369 outb((*(pred + i)) >> shift, 0x3C9);
370 outb((*(pgreen + i)) >> shift, 0x3C9);
371 outb((*(pblue + i)) >> shift, 0x3C9);
372 }
373 298
374 outb(0x1A, 0x3C4); 299 r = (red >> (16 - info->var.red.length))
375 outb(sr1a, 0x3C5); 300 << info->var.red.offset;
376 outb(0x1B, 0x3C4); 301 b = (blue >> (16 - info->var.blue.length))
377 outb(sr1b, 0x3C5); 302 << info->var.blue.offset;
378 outb(0x67, 0x3D4); 303 g = (green >> (16 - info->var.green.length))
379 outb(cr67, 0x3D5); 304 << info->var.green.offset;
380 outb(0x6A, 0x3D4); 305 ((u32 *) info->pseudo_palette)[regno] = r | g | b;
381 outb(cr6a, 0x3D5);
382 break;
383 case 16:
384 if (len > 17)
385 return 0; /* Because static u32 pseudo_pal[17]; */
386 for (i = 0; i < len; i++)
387 ((u32 *) info->pseudo_palette)[i] =
388 (*(pred + i) & 0xF800) |
389 ((*(pgreen + i) & 0xFC00) >> 5) |
390 ((*(pblue + i) & 0xF800) >> 11);
391 break;
392 case 32:
393 if (len > 17)
394 return 0;
395 if (ptransp) {
396 for (i = 0; i < len; i++)
397 ((u32 *) info->pseudo_palette)[i] =
398 ((*(ptransp + i) & 0xFF00) << 16) |
399 ((*(pred + i) & 0xFF00) << 8) |
400 ((*(pgreen + i) & 0xFF00)) |
401 ((*(pblue + i) & 0xFF00) >> 8);
402 } else {
403 for (i = 0; i < len; i++)
404 ((u32 *) info->pseudo_palette)[i] =
405 0x00000000 |
406 ((*(pred + i) & 0xFF00) << 8) |
407 ((*(pgreen + i) & 0xFF00)) |
408 ((*(pblue + i) & 0xFF00) >> 8);
409 }
410 break;
411 } 306 }
307
412 return 0; 308 return 0;
413} 309}
414 310
415static int viafb_pan_display(struct fb_var_screeninfo *var, 311static int viafb_pan_display(struct fb_var_screeninfo *var,
416 struct fb_info *info) 312 struct fb_info *info)
417{ 313{
418 unsigned int offset; 314 struct viafb_par *viapar = info->par;
419 315 u32 vram_addr = (var->yoffset * var->xres_virtual + var->xoffset)
420 DEBUG_MSG(KERN_INFO "viafb_pan_display!\n"); 316 * (var->bits_per_pixel / 8) + viapar->vram_addr;
421 317
422 offset = (var->xoffset + (var->yoffset * var->xres_virtual)) * 318 DEBUG_MSG(KERN_DEBUG "viafb_pan_display, address = %d\n", vram_addr);
423 var->bits_per_pixel / 16; 319 if (!viafb_dual_fb) {
320 viafb_set_primary_address(vram_addr);
321 viafb_set_secondary_address(vram_addr);
322 } else if (viapar->iga_path == IGA1)
323 viafb_set_primary_address(vram_addr);
324 else
325 viafb_set_secondary_address(vram_addr);
424 326
425 DEBUG_MSG(KERN_INFO "\nviafb_pan_display,offset =%d ", offset);
426 viafb_set_primary_address(offset);
427 return 0; 327 return 0;
428} 328}
429 329
@@ -477,6 +377,7 @@ static int viafb_ioctl(struct fb_info *info, u_int cmd, u_long arg)
477 u32 gpu32; 377 u32 gpu32;
478 378
479 DEBUG_MSG(KERN_INFO "viafb_ioctl: 0x%X !!\n", cmd); 379 DEBUG_MSG(KERN_INFO "viafb_ioctl: 0x%X !!\n", cmd);
380 printk(KERN_WARNING "viafb_ioctl: Please avoid this interface as it is unstable and might change or vanish at any time!\n");
480 memset(&u, 0, sizeof(u)); 381 memset(&u, 0, sizeof(u));
481 382
482 switch (cmd) { 383 switch (cmd) {
@@ -680,7 +581,7 @@ static int viafb_ioctl(struct fb_info *info, u_int cmd, u_long arg)
680 if (!viafb_gamma_table) 581 if (!viafb_gamma_table)
681 return -ENOMEM; 582 return -ENOMEM;
682 if (copy_from_user(viafb_gamma_table, argp, 583 if (copy_from_user(viafb_gamma_table, argp,
683 sizeof(viafb_gamma_table))) { 584 256 * sizeof(u32))) {
684 kfree(viafb_gamma_table); 585 kfree(viafb_gamma_table);
685 return -EFAULT; 586 return -EFAULT;
686 } 587 }
@@ -694,7 +595,7 @@ static int viafb_ioctl(struct fb_info *info, u_int cmd, u_long arg)
694 return -ENOMEM; 595 return -ENOMEM;
695 viafb_get_gamma_table(viafb_gamma_table); 596 viafb_get_gamma_table(viafb_gamma_table);
696 if (copy_to_user(argp, viafb_gamma_table, 597 if (copy_to_user(argp, viafb_gamma_table,
697 sizeof(viafb_gamma_table))) { 598 256 * sizeof(u32))) {
698 kfree(viafb_gamma_table); 599 kfree(viafb_gamma_table);
699 return -EFAULT; 600 return -EFAULT;
700 } 601 }
@@ -872,7 +773,9 @@ static int viafb_cursor(struct fb_info *info, struct fb_cursor *cursor)
872 if (info->flags & FBINFO_HWACCEL_DISABLED || info != viafbinfo) 773 if (info->flags & FBINFO_HWACCEL_DISABLED || info != viafbinfo)
873 return -ENODEV; 774 return -ENODEV;
874 775
875 if (chip_name == UNICHROME_CLE266 && viapar->iga_path == IGA2) 776 /* LCD ouput does not support hw cursors (at least on VN896) */
777 if ((chip_name == UNICHROME_CLE266 && viapar->iga_path == IGA2) ||
778 viafb_LCD_ON)
876 return -ENODEV; 779 return -ENODEV;
877 780
878 viafb_show_hw_cursor(info, HW_Cursor_OFF); 781 viafb_show_hw_cursor(info, HW_Cursor_OFF);
@@ -1014,23 +917,6 @@ static int viafb_sync(struct fb_info *info)
1014 return 0; 917 return 0;
1015} 918}
1016 919
1017int viafb_get_mode_index(int hres, int vres)
1018{
1019 u32 i;
1020 DEBUG_MSG(KERN_INFO "viafb_get_mode_index!\n");
1021
1022 for (i = 0; i < NUM_TOTAL_MODETABLE; i++)
1023 if (CLE266Modes[i].mode_array &&
1024 CLE266Modes[i].crtc[0].crtc.hor_addr == hres &&
1025 CLE266Modes[i].crtc[0].crtc.ver_addr == vres)
1026 break;
1027
1028 if (i == NUM_TOTAL_MODETABLE)
1029 return VIA_RES_INVALID;
1030
1031 return CLE266Modes[i].ModeIndex;
1032}
1033
1034static void check_available_device_to_enable(int device_id) 920static void check_available_device_to_enable(int device_id)
1035{ 921{
1036 int device_num = 0; 922 int device_num = 0;
@@ -1329,7 +1215,7 @@ static void retrieve_device_setting(struct viafb_ioctl_setting
1329 setting_info->lcd_attributes.lcd_mode = viafb_lcd_mode; 1215 setting_info->lcd_attributes.lcd_mode = viafb_lcd_mode;
1330} 1216}
1331 1217
1332static void parse_active_dev(void) 1218static int parse_active_dev(void)
1333{ 1219{
1334 viafb_CRT_ON = STATE_OFF; 1220 viafb_CRT_ON = STATE_OFF;
1335 viafb_DVI_ON = STATE_OFF; 1221 viafb_DVI_ON = STATE_OFF;
@@ -1340,60 +1226,63 @@ static void parse_active_dev(void)
1340 IGA path to devices in SAMM case. */ 1226 IGA path to devices in SAMM case. */
1341 /* Note: The previous of active_dev is primary device, 1227 /* Note: The previous of active_dev is primary device,
1342 and the following is secondary device. */ 1228 and the following is secondary device. */
1343 if (!strncmp(viafb_active_dev, "CRT+DVI", 7)) { 1229 if (!viafb_active_dev) {
1230 viafb_CRT_ON = STATE_ON;
1231 viafb_SAMM_ON = STATE_OFF;
1232 } else if (!strcmp(viafb_active_dev, "CRT+DVI")) {
1344 /* CRT+DVI */ 1233 /* CRT+DVI */
1345 viafb_CRT_ON = STATE_ON; 1234 viafb_CRT_ON = STATE_ON;
1346 viafb_DVI_ON = STATE_ON; 1235 viafb_DVI_ON = STATE_ON;
1347 viafb_primary_dev = CRT_Device; 1236 viafb_primary_dev = CRT_Device;
1348 } else if (!strncmp(viafb_active_dev, "DVI+CRT", 7)) { 1237 } else if (!strcmp(viafb_active_dev, "DVI+CRT")) {
1349 /* DVI+CRT */ 1238 /* DVI+CRT */
1350 viafb_CRT_ON = STATE_ON; 1239 viafb_CRT_ON = STATE_ON;
1351 viafb_DVI_ON = STATE_ON; 1240 viafb_DVI_ON = STATE_ON;
1352 viafb_primary_dev = DVI_Device; 1241 viafb_primary_dev = DVI_Device;
1353 } else if (!strncmp(viafb_active_dev, "CRT+LCD", 7)) { 1242 } else if (!strcmp(viafb_active_dev, "CRT+LCD")) {
1354 /* CRT+LCD */ 1243 /* CRT+LCD */
1355 viafb_CRT_ON = STATE_ON; 1244 viafb_CRT_ON = STATE_ON;
1356 viafb_LCD_ON = STATE_ON; 1245 viafb_LCD_ON = STATE_ON;
1357 viafb_primary_dev = CRT_Device; 1246 viafb_primary_dev = CRT_Device;
1358 } else if (!strncmp(viafb_active_dev, "LCD+CRT", 7)) { 1247 } else if (!strcmp(viafb_active_dev, "LCD+CRT")) {
1359 /* LCD+CRT */ 1248 /* LCD+CRT */
1360 viafb_CRT_ON = STATE_ON; 1249 viafb_CRT_ON = STATE_ON;
1361 viafb_LCD_ON = STATE_ON; 1250 viafb_LCD_ON = STATE_ON;
1362 viafb_primary_dev = LCD_Device; 1251 viafb_primary_dev = LCD_Device;
1363 } else if (!strncmp(viafb_active_dev, "DVI+LCD", 7)) { 1252 } else if (!strcmp(viafb_active_dev, "DVI+LCD")) {
1364 /* DVI+LCD */ 1253 /* DVI+LCD */
1365 viafb_DVI_ON = STATE_ON; 1254 viafb_DVI_ON = STATE_ON;
1366 viafb_LCD_ON = STATE_ON; 1255 viafb_LCD_ON = STATE_ON;
1367 viafb_primary_dev = DVI_Device; 1256 viafb_primary_dev = DVI_Device;
1368 } else if (!strncmp(viafb_active_dev, "LCD+DVI", 7)) { 1257 } else if (!strcmp(viafb_active_dev, "LCD+DVI")) {
1369 /* LCD+DVI */ 1258 /* LCD+DVI */
1370 viafb_DVI_ON = STATE_ON; 1259 viafb_DVI_ON = STATE_ON;
1371 viafb_LCD_ON = STATE_ON; 1260 viafb_LCD_ON = STATE_ON;
1372 viafb_primary_dev = LCD_Device; 1261 viafb_primary_dev = LCD_Device;
1373 } else if (!strncmp(viafb_active_dev, "LCD+LCD2", 8)) { 1262 } else if (!strcmp(viafb_active_dev, "LCD+LCD2")) {
1374 viafb_LCD_ON = STATE_ON; 1263 viafb_LCD_ON = STATE_ON;
1375 viafb_LCD2_ON = STATE_ON; 1264 viafb_LCD2_ON = STATE_ON;
1376 viafb_primary_dev = LCD_Device; 1265 viafb_primary_dev = LCD_Device;
1377 } else if (!strncmp(viafb_active_dev, "LCD2+LCD", 8)) { 1266 } else if (!strcmp(viafb_active_dev, "LCD2+LCD")) {
1378 viafb_LCD_ON = STATE_ON; 1267 viafb_LCD_ON = STATE_ON;
1379 viafb_LCD2_ON = STATE_ON; 1268 viafb_LCD2_ON = STATE_ON;
1380 viafb_primary_dev = LCD2_Device; 1269 viafb_primary_dev = LCD2_Device;
1381 } else if (!strncmp(viafb_active_dev, "CRT", 3)) { 1270 } else if (!strcmp(viafb_active_dev, "CRT")) {
1382 /* CRT only */ 1271 /* CRT only */
1383 viafb_CRT_ON = STATE_ON; 1272 viafb_CRT_ON = STATE_ON;
1384 viafb_SAMM_ON = STATE_OFF; 1273 viafb_SAMM_ON = STATE_OFF;
1385 } else if (!strncmp(viafb_active_dev, "DVI", 3)) { 1274 } else if (!strcmp(viafb_active_dev, "DVI")) {
1386 /* DVI only */ 1275 /* DVI only */
1387 viafb_DVI_ON = STATE_ON; 1276 viafb_DVI_ON = STATE_ON;
1388 viafb_SAMM_ON = STATE_OFF; 1277 viafb_SAMM_ON = STATE_OFF;
1389 } else if (!strncmp(viafb_active_dev, "LCD", 3)) { 1278 } else if (!strcmp(viafb_active_dev, "LCD")) {
1390 /* LCD only */ 1279 /* LCD only */
1391 viafb_LCD_ON = STATE_ON; 1280 viafb_LCD_ON = STATE_ON;
1392 viafb_SAMM_ON = STATE_OFF; 1281 viafb_SAMM_ON = STATE_OFF;
1393 } else { 1282 } else
1394 viafb_CRT_ON = STATE_ON; 1283 return -EINVAL;
1395 viafb_SAMM_ON = STATE_OFF; 1284
1396 } 1285 return 0;
1397} 1286}
1398 1287
1399static int parse_port(char *opt_str, int *output_interface) 1288static int parse_port(char *opt_str, int *output_interface)
@@ -1797,7 +1686,7 @@ static const struct file_operations viafb_vt1636_proc_fops = {
1797static void viafb_init_proc(struct proc_dir_entry **viafb_entry) 1686static void viafb_init_proc(struct proc_dir_entry **viafb_entry)
1798{ 1687{
1799 *viafb_entry = proc_mkdir("viafb", NULL); 1688 *viafb_entry = proc_mkdir("viafb", NULL);
1800 if (viafb_entry) { 1689 if (*viafb_entry) {
1801 proc_create("dvp0", 0, *viafb_entry, &viafb_dvp0_proc_fops); 1690 proc_create("dvp0", 0, *viafb_entry, &viafb_dvp0_proc_fops);
1802 proc_create("dvp1", 0, *viafb_entry, &viafb_dvp1_proc_fops); 1691 proc_create("dvp1", 0, *viafb_entry, &viafb_dvp1_proc_fops);
1803 proc_create("dfph", 0, *viafb_entry, &viafb_dfph_proc_fops); 1692 proc_create("dfph", 0, *viafb_entry, &viafb_dfph_proc_fops);
@@ -1822,35 +1711,37 @@ static void viafb_remove_proc(struct proc_dir_entry *viafb_entry)
1822 remove_proc_entry("viafb", NULL); 1711 remove_proc_entry("viafb", NULL);
1823} 1712}
1824 1713
1825static void parse_mode(const char *str, u32 *xres, u32 *yres) 1714static int parse_mode(const char *str, u32 *xres, u32 *yres)
1826{ 1715{
1827 char *ptr; 1716 char *ptr;
1828 1717
1718 if (!str) {
1719 *xres = 640;
1720 *yres = 480;
1721 return 0;
1722 }
1723
1829 *xres = simple_strtoul(str, &ptr, 10); 1724 *xres = simple_strtoul(str, &ptr, 10);
1830 if (ptr[0] != 'x') 1725 if (ptr[0] != 'x')
1831 goto out_default; 1726 return -EINVAL;
1832 1727
1833 *yres = simple_strtoul(&ptr[1], &ptr, 10); 1728 *yres = simple_strtoul(&ptr[1], &ptr, 10);
1834 if (ptr[0]) 1729 if (ptr[0])
1835 goto out_default; 1730 return -EINVAL;
1836
1837 return;
1838 1731
1839out_default: 1732 return 0;
1840 printk(KERN_WARNING "viafb received invalid mode string: %s\n", str);
1841 *xres = 640;
1842 *yres = 480;
1843} 1733}
1844 1734
1845static int __devinit via_pci_probe(struct pci_dev *pdev, 1735static int __devinit via_pci_probe(struct pci_dev *pdev,
1846 const struct pci_device_id *ent) 1736 const struct pci_device_id *ent)
1847{ 1737{
1848 u32 default_xres, default_yres; 1738 u32 default_xres, default_yres;
1849 int vmode_index; 1739 struct VideoModeTable *vmode_entry;
1740 struct fb_var_screeninfo default_var;
1850 u32 viafb_par_length; 1741 u32 viafb_par_length;
1851 1742
1852 DEBUG_MSG(KERN_INFO "VIAFB PCI Probe!!\n"); 1743 DEBUG_MSG(KERN_INFO "VIAFB PCI Probe!!\n");
1853 1744 memset(&default_var, 0, sizeof(default_var));
1854 viafb_par_length = ALIGN(sizeof(struct viafb_par), BITS_PER_LONG/8); 1745 viafb_par_length = ALIGN(sizeof(struct viafb_par), BITS_PER_LONG/8);
1855 1746
1856 /* Allocate fb_info and ***_par here, also including some other needed 1747 /* Allocate fb_info and ***_par here, also including some other needed
@@ -1876,7 +1767,6 @@ static int __devinit via_pci_probe(struct pci_dev *pdev,
1876 1767
1877 if (viafb_dual_fb) 1768 if (viafb_dual_fb)
1878 viafb_SAMM_ON = 1; 1769 viafb_SAMM_ON = 1;
1879 parse_active_dev();
1880 parse_lcd_port(); 1770 parse_lcd_port();
1881 parse_dvi_port(); 1771 parse_dvi_port();
1882 1772
@@ -1925,9 +1815,7 @@ static int __devinit via_pci_probe(struct pci_dev *pdev,
1925 } 1815 }
1926 1816
1927 parse_mode(viafb_mode, &default_xres, &default_yres); 1817 parse_mode(viafb_mode, &default_xres, &default_yres);
1928 vmode_index = viafb_get_mode_index(default_xres, default_yres); 1818 vmode_entry = viafb_get_mode(default_xres, default_yres);
1929 DEBUG_MSG(KERN_INFO "0->index=%d\n", vmode_index);
1930
1931 if (viafb_SAMM_ON == 1) { 1819 if (viafb_SAMM_ON == 1) {
1932 parse_mode(viafb_mode1, &viafb_second_xres, 1820 parse_mode(viafb_mode1, &viafb_second_xres,
1933 &viafb_second_yres); 1821 &viafb_second_yres);
@@ -1946,19 +1834,6 @@ static int __devinit via_pci_probe(struct pci_dev *pdev,
1946 viafb_second_virtual_yres = viafb_second_yres; 1834 viafb_second_virtual_yres = viafb_second_yres;
1947 } 1835 }
1948 1836
1949 switch (viafb_bpp) {
1950 case 0 ... 8:
1951 viafb_bpp = 8;
1952 break;
1953 case 9 ... 16:
1954 viafb_bpp = 16;
1955 break;
1956 case 17 ... 32:
1957 viafb_bpp = 32;
1958 break;
1959 default:
1960 viafb_bpp = 8;
1961 }
1962 default_var.xres = default_xres; 1837 default_var.xres = default_xres;
1963 default_var.yres = default_yres; 1838 default_var.yres = default_yres;
1964 switch (default_xres) { 1839 switch (default_xres) {
@@ -1971,8 +1846,6 @@ static int __devinit via_pci_probe(struct pci_dev *pdev,
1971 } 1846 }
1972 default_var.yres_virtual = default_yres; 1847 default_var.yres_virtual = default_yres;
1973 default_var.bits_per_pixel = viafb_bpp; 1848 default_var.bits_per_pixel = viafb_bpp;
1974 if (default_var.bits_per_pixel == 15)
1975 default_var.bits_per_pixel = 16;
1976 default_var.pixclock = 1849 default_var.pixclock =
1977 viafb_get_pixclock(default_xres, default_yres, viafb_refresh); 1850 viafb_get_pixclock(default_xres, default_yres, viafb_refresh);
1978 default_var.left_margin = (default_xres >> 3) & 0xf8; 1851 default_var.left_margin = (default_xres >> 3) & 0xf8;
@@ -1981,6 +1854,8 @@ static int __devinit via_pci_probe(struct pci_dev *pdev,
1981 default_var.lower_margin = 4; 1854 default_var.lower_margin = 4;
1982 default_var.hsync_len = default_var.left_margin; 1855 default_var.hsync_len = default_var.left_margin;
1983 default_var.vsync_len = 4; 1856 default_var.vsync_len = 4;
1857 viafb_setup_fixinfo(&viafbinfo->fix, viaparinfo);
1858 viafbinfo->var = default_var;
1984 1859
1985 if (viafb_dual_fb) { 1860 if (viafb_dual_fb) {
1986 viafbinfo1 = framebuffer_alloc(viafb_par_length, &pdev->dev); 1861 viafbinfo1 = framebuffer_alloc(viafb_par_length, &pdev->dev);
@@ -2015,8 +1890,6 @@ static int __devinit via_pci_probe(struct pci_dev *pdev,
2015 default_var.yres = viafb_second_yres; 1890 default_var.yres = viafb_second_yres;
2016 default_var.xres_virtual = viafb_second_virtual_xres; 1891 default_var.xres_virtual = viafb_second_virtual_xres;
2017 default_var.yres_virtual = viafb_second_virtual_yres; 1892 default_var.yres_virtual = viafb_second_virtual_yres;
2018 if (viafb_bpp1 != viafb_bpp)
2019 viafb_bpp1 = viafb_bpp;
2020 default_var.bits_per_pixel = viafb_bpp1; 1893 default_var.bits_per_pixel = viafb_bpp1;
2021 default_var.pixclock = 1894 default_var.pixclock =
2022 viafb_get_pixclock(viafb_second_xres, viafb_second_yres, 1895 viafb_get_pixclock(viafb_second_xres, viafb_second_yres,
@@ -2036,9 +1909,7 @@ static int __devinit via_pci_probe(struct pci_dev *pdev,
2036 &viafbinfo1->fix); 1909 &viafbinfo1->fix);
2037 } 1910 }
2038 1911
2039 viafb_setup_fixinfo(&viafbinfo->fix, viaparinfo); 1912 viafb_check_var(&viafbinfo->var, viafbinfo);
2040 viafb_check_var(&default_var, viafbinfo);
2041 viafbinfo->var = default_var;
2042 viafb_update_fix(viafbinfo); 1913 viafb_update_fix(viafbinfo);
2043 viaparinfo->depth = fb_get_color_depth(&viafbinfo->var, 1914 viaparinfo->depth = fb_get_color_depth(&viafbinfo->var,
2044 &viafbinfo->fix); 1915 &viafbinfo->fix);
@@ -2196,12 +2067,20 @@ static struct pci_driver viafb_driver = {
2196 2067
2197static int __init viafb_init(void) 2068static int __init viafb_init(void)
2198{ 2069{
2070 u32 dummy;
2199#ifndef MODULE 2071#ifndef MODULE
2200 char *option = NULL; 2072 char *option = NULL;
2201 if (fb_get_options("viafb", &option)) 2073 if (fb_get_options("viafb", &option))
2202 return -ENODEV; 2074 return -ENODEV;
2203 viafb_setup(option); 2075 viafb_setup(option);
2204#endif 2076#endif
2077 if (parse_mode(viafb_mode, &dummy, &dummy)
2078 || parse_mode(viafb_mode1, &dummy, &dummy)
2079 || viafb_bpp < 0 || viafb_bpp > 32
2080 || viafb_bpp1 < 0 || viafb_bpp1 > 32
2081 || parse_active_dev())
2082 return -EINVAL;
2083
2205 printk(KERN_INFO 2084 printk(KERN_INFO
2206 "VIA Graphics Intergration Chipset framebuffer %d.%d initializing\n", 2085 "VIA Graphics Intergration Chipset framebuffer %d.%d initializing\n",
2207 VERSION_MAJOR, VERSION_MINOR); 2086 VERSION_MAJOR, VERSION_MINOR);
@@ -2229,15 +2108,12 @@ static struct fb_ops viafb_ops = {
2229 .fb_cursor = viafb_cursor, 2108 .fb_cursor = viafb_cursor,
2230 .fb_ioctl = viafb_ioctl, 2109 .fb_ioctl = viafb_ioctl,
2231 .fb_sync = viafb_sync, 2110 .fb_sync = viafb_sync,
2232 .fb_setcmap = viafb_setcmap,
2233}; 2111};
2234 2112
2235module_init(viafb_init); 2113module_init(viafb_init);
2236module_exit(viafb_exit); 2114module_exit(viafb_exit);
2237 2115
2238#ifdef MODULE 2116#ifdef MODULE
2239module_param(viafb_memsize, int, S_IRUSR);
2240
2241module_param(viafb_mode, charp, S_IRUSR); 2117module_param(viafb_mode, charp, S_IRUSR);
2242MODULE_PARM_DESC(viafb_mode, "Set resolution (default=640x480)"); 2118MODULE_PARM_DESC(viafb_mode, "Set resolution (default=640x480)");
2243 2119