diff options
Diffstat (limited to 'drivers/video/via/viafbdev.c')
-rw-r--r-- | drivers/video/via/viafbdev.c | 237 |
1 files changed, 25 insertions, 212 deletions
diff --git a/drivers/video/via/viafbdev.c b/drivers/video/via/viafbdev.c index 0fe748d66a6c..410de33f5778 100644 --- a/drivers/video/via/viafbdev.c +++ b/drivers/video/via/viafbdev.c | |||
@@ -76,9 +76,9 @@ static void viafb_fill_var_color_info(struct fb_var_screeninfo *var, u8 depth) | |||
76 | var->red.offset = 0; | 76 | var->red.offset = 0; |
77 | var->green.offset = 0; | 77 | var->green.offset = 0; |
78 | var->blue.offset = 0; | 78 | var->blue.offset = 0; |
79 | var->red.length = 6; | 79 | var->red.length = 8; |
80 | var->green.length = 6; | 80 | var->green.length = 8; |
81 | var->blue.length = 6; | 81 | var->blue.length = 8; |
82 | break; | 82 | break; |
83 | case 16: | 83 | case 16: |
84 | var->bits_per_pixel = 16; | 84 | var->bits_per_pixel = 16; |
@@ -255,219 +255,33 @@ static int viafb_set_par(struct fb_info *info) | |||
255 | static int viafb_setcolreg(unsigned regno, unsigned red, unsigned green, | 255 | static int viafb_setcolreg(unsigned regno, unsigned red, unsigned green, |
256 | unsigned blue, unsigned transp, struct fb_info *info) | 256 | unsigned blue, unsigned transp, struct fb_info *info) |
257 | { | 257 | { |
258 | u8 sr1a, sr1b, cr67, cr6a, rev = 0, shift = 10; | 258 | struct viafb_par *viapar = info->par; |
259 | unsigned cmap_entries = (info->var.bits_per_pixel == 8) ? 256 : 16; | 259 | u32 r, g, b; |
260 | DEBUG_MSG(KERN_INFO "viafb_setcolreg!\n"); | ||
261 | if (regno >= cmap_entries) | ||
262 | return 1; | ||
263 | if (UNICHROME_CLE266 == viaparinfo->chip_info->gfx_chip_name) { | ||
264 | /* | ||
265 | * Read PCI bus 0,dev 0,function 0,index 0xF6 to get chip rev. | ||
266 | */ | ||
267 | outl(0x80000000 | (0xf6 & ~3), (unsigned long)0xCF8); | ||
268 | rev = (inl((unsigned long)0xCFC) >> ((0xf6 & 3) * 8)) & 0xff; | ||
269 | } | ||
270 | switch (info->var.bits_per_pixel) { | ||
271 | case 8: | ||
272 | outb(0x1A, 0x3C4); | ||
273 | sr1a = inb(0x3C5); | ||
274 | outb(0x1B, 0x3C4); | ||
275 | sr1b = inb(0x3C5); | ||
276 | outb(0x67, 0x3D4); | ||
277 | cr67 = inb(0x3D5); | ||
278 | outb(0x6A, 0x3D4); | ||
279 | cr6a = inb(0x3D5); | ||
280 | |||
281 | /* Map the 3C6/7/8/9 to the IGA2 */ | ||
282 | outb(0x1A, 0x3C4); | ||
283 | outb(sr1a | 0x01, 0x3C5); | ||
284 | /* Second Display Engine colck always on */ | ||
285 | outb(0x1B, 0x3C4); | ||
286 | outb(sr1b | 0x80, 0x3C5); | ||
287 | /* Second Display Color Depth 8 */ | ||
288 | outb(0x67, 0x3D4); | ||
289 | outb(cr67 & 0x3F, 0x3D5); | ||
290 | outb(0x6A, 0x3D4); | ||
291 | /* Second Display Channel Reset CR6A[6]) */ | ||
292 | outb(cr6a & 0xBF, 0x3D5); | ||
293 | /* Second Display Channel Enable CR6A[7] */ | ||
294 | outb(cr6a | 0x80, 0x3D5); | ||
295 | /* Second Display Channel stop reset) */ | ||
296 | outb(cr6a | 0x40, 0x3D5); | ||
297 | |||
298 | /* Bit mask of palette */ | ||
299 | outb(0xFF, 0x3c6); | ||
300 | /* Write one register of IGA2 */ | ||
301 | outb(regno, 0x3C8); | ||
302 | if (UNICHROME_CLE266 == viaparinfo->chip_info->gfx_chip_name && | ||
303 | rev >= 15) { | ||
304 | shift = 8; | ||
305 | viafb_write_reg_mask(CR6A, VIACR, BIT5, BIT5); | ||
306 | viafb_write_reg_mask(SR15, VIASR, BIT7, BIT7); | ||
307 | } else { | ||
308 | shift = 10; | ||
309 | viafb_write_reg_mask(CR6A, VIACR, 0, BIT5); | ||
310 | viafb_write_reg_mask(SR15, VIASR, 0, BIT7); | ||
311 | } | ||
312 | outb(red >> shift, 0x3C9); | ||
313 | outb(green >> shift, 0x3C9); | ||
314 | outb(blue >> shift, 0x3C9); | ||
315 | |||
316 | /* Map the 3C6/7/8/9 to the IGA1 */ | ||
317 | outb(0x1A, 0x3C4); | ||
318 | outb(sr1a & 0xFE, 0x3C5); | ||
319 | /* Bit mask of palette */ | ||
320 | outb(0xFF, 0x3c6); | ||
321 | /* Write one register of IGA1 */ | ||
322 | outb(regno, 0x3C8); | ||
323 | outb(red >> shift, 0x3C9); | ||
324 | outb(green >> shift, 0x3C9); | ||
325 | outb(blue >> shift, 0x3C9); | ||
326 | |||
327 | outb(0x1A, 0x3C4); | ||
328 | outb(sr1a, 0x3C5); | ||
329 | outb(0x1B, 0x3C4); | ||
330 | outb(sr1b, 0x3C5); | ||
331 | outb(0x67, 0x3D4); | ||
332 | outb(cr67, 0x3D5); | ||
333 | outb(0x6A, 0x3D4); | ||
334 | outb(cr6a, 0x3D5); | ||
335 | break; | ||
336 | case 16: | ||
337 | ((u32 *) info->pseudo_palette)[regno] = (red & 0xF800) | | ||
338 | ((green & 0xFC00) >> 5) | ((blue & 0xF800) >> 11); | ||
339 | break; | ||
340 | case 32: | ||
341 | ((u32 *) info->pseudo_palette)[regno] = | ||
342 | ((transp & 0xFF00) << 16) | | ||
343 | ((red & 0xFF00) << 8) | | ||
344 | ((green & 0xFF00)) | ((blue & 0xFF00) >> 8); | ||
345 | break; | ||
346 | } | ||
347 | |||
348 | return 0; | ||
349 | 260 | ||
350 | } | 261 | if (info->fix.visual == FB_VISUAL_PSEUDOCOLOR) { |
262 | if (regno > 255) | ||
263 | return -EINVAL; | ||
351 | 264 | ||
352 | /*CALLED BY: fb_set_cmap */ | 265 | if (!viafb_dual_fb || viapar->iga_path == IGA1) |
353 | /* fb_set_var, pass 256 colors */ | 266 | viafb_set_primary_color_register(regno, red >> 8, |
354 | /*CALLED BY: fb_set_cmap */ | 267 | green >> 8, blue >> 8); |
355 | /* fbcon_set_palette, pass 16 colors */ | ||
356 | static int viafb_setcmap(struct fb_cmap *cmap, struct fb_info *info) | ||
357 | { | ||
358 | u32 len = cmap->len; | ||
359 | u32 i; | ||
360 | u16 *pred = cmap->red; | ||
361 | u16 *pgreen = cmap->green; | ||
362 | u16 *pblue = cmap->blue; | ||
363 | u16 *ptransp = cmap->transp; | ||
364 | u8 sr1a, sr1b, cr67, cr6a, rev = 0, shift = 10; | ||
365 | if (len > 256) | ||
366 | return 1; | ||
367 | if (UNICHROME_CLE266 == viaparinfo->chip_info->gfx_chip_name) { | ||
368 | /* | ||
369 | * Read PCI bus 0, dev 0, function 0, index 0xF6 to get chip | ||
370 | * rev. | ||
371 | */ | ||
372 | outl(0x80000000 | (0xf6 & ~3), (unsigned long)0xCF8); | ||
373 | rev = (inl((unsigned long)0xCFC) >> ((0xf6 & 3) * 8)) & 0xff; | ||
374 | } | ||
375 | switch (info->var.bits_per_pixel) { | ||
376 | case 8: | ||
377 | outb(0x1A, 0x3C4); | ||
378 | sr1a = inb(0x3C5); | ||
379 | outb(0x1B, 0x3C4); | ||
380 | sr1b = inb(0x3C5); | ||
381 | outb(0x67, 0x3D4); | ||
382 | cr67 = inb(0x3D5); | ||
383 | outb(0x6A, 0x3D4); | ||
384 | cr6a = inb(0x3D5); | ||
385 | /* Map the 3C6/7/8/9 to the IGA2 */ | ||
386 | outb(0x1A, 0x3C4); | ||
387 | outb(sr1a | 0x01, 0x3C5); | ||
388 | outb(0x1B, 0x3C4); | ||
389 | /* Second Display Engine colck always on */ | ||
390 | outb(sr1b | 0x80, 0x3C5); | ||
391 | outb(0x67, 0x3D4); | ||
392 | /* Second Display Color Depth 8 */ | ||
393 | outb(cr67 & 0x3F, 0x3D5); | ||
394 | outb(0x6A, 0x3D4); | ||
395 | /* Second Display Channel Reset CR6A[6]) */ | ||
396 | outb(cr6a & 0xBF, 0x3D5); | ||
397 | /* Second Display Channel Enable CR6A[7] */ | ||
398 | outb(cr6a | 0x80, 0x3D5); | ||
399 | /* Second Display Channel stop reset) */ | ||
400 | outb(cr6a | 0xC0, 0x3D5); | ||
401 | |||
402 | /* Bit mask of palette */ | ||
403 | outb(0xFF, 0x3c6); | ||
404 | outb(0x00, 0x3C8); | ||
405 | if (UNICHROME_CLE266 == viaparinfo->chip_info->gfx_chip_name && | ||
406 | rev >= 15) { | ||
407 | shift = 8; | ||
408 | viafb_write_reg_mask(CR6A, VIACR, BIT5, BIT5); | ||
409 | viafb_write_reg_mask(SR15, VIASR, BIT7, BIT7); | ||
410 | } else { | ||
411 | shift = 10; | ||
412 | viafb_write_reg_mask(CR6A, VIACR, 0, BIT5); | ||
413 | viafb_write_reg_mask(SR15, VIASR, 0, BIT7); | ||
414 | } | ||
415 | for (i = 0; i < len; i++) { | ||
416 | outb((*(pred + i)) >> shift, 0x3C9); | ||
417 | outb((*(pgreen + i)) >> shift, 0x3C9); | ||
418 | outb((*(pblue + i)) >> shift, 0x3C9); | ||
419 | } | ||
420 | 268 | ||
421 | outb(0x1A, 0x3C4); | 269 | if (!viafb_dual_fb || viapar->iga_path == IGA2) |
422 | /* Map the 3C6/7/8/9 to the IGA1 */ | 270 | viafb_set_secondary_color_register(regno, red >> 8, |
423 | outb(sr1a & 0xFE, 0x3C5); | 271 | green >> 8, blue >> 8); |
424 | /* Bit mask of palette */ | 272 | } else { |
425 | outb(0xFF, 0x3c6); | 273 | if (regno > 15) |
426 | outb(0x00, 0x3C8); | 274 | return -EINVAL; |
427 | for (i = 0; i < len; i++) { | ||
428 | outb((*(pred + i)) >> shift, 0x3C9); | ||
429 | outb((*(pgreen + i)) >> shift, 0x3C9); | ||
430 | outb((*(pblue + i)) >> shift, 0x3C9); | ||
431 | } | ||
432 | 275 | ||
433 | outb(0x1A, 0x3C4); | 276 | r = (red >> (16 - info->var.red.length)) |
434 | outb(sr1a, 0x3C5); | 277 | << info->var.red.offset; |
435 | outb(0x1B, 0x3C4); | 278 | b = (blue >> (16 - info->var.blue.length)) |
436 | outb(sr1b, 0x3C5); | 279 | << info->var.blue.offset; |
437 | outb(0x67, 0x3D4); | 280 | g = (green >> (16 - info->var.green.length)) |
438 | outb(cr67, 0x3D5); | 281 | << info->var.green.offset; |
439 | outb(0x6A, 0x3D4); | 282 | ((u32 *) info->pseudo_palette)[regno] = r | g | b; |
440 | outb(cr6a, 0x3D5); | ||
441 | break; | ||
442 | case 16: | ||
443 | if (len > 17) | ||
444 | return 0; /* Because static u32 pseudo_pal[17]; */ | ||
445 | for (i = 0; i < len; i++) | ||
446 | ((u32 *) info->pseudo_palette)[i] = | ||
447 | (*(pred + i) & 0xF800) | | ||
448 | ((*(pgreen + i) & 0xFC00) >> 5) | | ||
449 | ((*(pblue + i) & 0xF800) >> 11); | ||
450 | break; | ||
451 | case 32: | ||
452 | if (len > 17) | ||
453 | return 0; | ||
454 | if (ptransp) { | ||
455 | for (i = 0; i < len; i++) | ||
456 | ((u32 *) info->pseudo_palette)[i] = | ||
457 | ((*(ptransp + i) & 0xFF00) << 16) | | ||
458 | ((*(pred + i) & 0xFF00) << 8) | | ||
459 | ((*(pgreen + i) & 0xFF00)) | | ||
460 | ((*(pblue + i) & 0xFF00) >> 8); | ||
461 | } else { | ||
462 | for (i = 0; i < len; i++) | ||
463 | ((u32 *) info->pseudo_palette)[i] = | ||
464 | 0x00000000 | | ||
465 | ((*(pred + i) & 0xFF00) << 8) | | ||
466 | ((*(pgreen + i) & 0xFF00)) | | ||
467 | ((*(pblue + i) & 0xFF00) >> 8); | ||
468 | } | ||
469 | break; | ||
470 | } | 283 | } |
284 | |||
471 | return 0; | 285 | return 0; |
472 | } | 286 | } |
473 | 287 | ||
@@ -2286,7 +2100,6 @@ static struct fb_ops viafb_ops = { | |||
2286 | .fb_cursor = viafb_cursor, | 2100 | .fb_cursor = viafb_cursor, |
2287 | .fb_ioctl = viafb_ioctl, | 2101 | .fb_ioctl = viafb_ioctl, |
2288 | .fb_sync = viafb_sync, | 2102 | .fb_sync = viafb_sync, |
2289 | .fb_setcmap = viafb_setcmap, | ||
2290 | }; | 2103 | }; |
2291 | 2104 | ||
2292 | module_init(viafb_init); | 2105 | module_init(viafb_init); |