15 #include <linux/module.h>
16 #include <linux/kernel.h>
17 #include <linux/errno.h>
18 #include <linux/string.h>
28 #include <linux/pci.h>
32 #include <asm/pci-bridge.h>
36 #include <asm/bootx.h>
68 #define AVIVO_DC_LUT_RW_SELECT 0x6480
69 #define AVIVO_DC_LUT_RW_MODE 0x6484
70 #define AVIVO_DC_LUT_RW_INDEX 0x6488
71 #define AVIVO_DC_LUT_SEQ_COLOR 0x648c
72 #define AVIVO_DC_LUT_PWL_DATA 0x6490
73 #define AVIVO_DC_LUT_30_COLOR 0x6494
74 #define AVIVO_DC_LUT_READ_PIPE_SELECT 0x6498
75 #define AVIVO_DC_LUT_WRITE_EN_MASK 0x649c
76 #define AVIVO_DC_LUT_AUTOFILL 0x64a0
78 #define AVIVO_DC_LUTA_CONTROL 0x64c0
79 #define AVIVO_DC_LUTA_BLACK_OFFSET_BLUE 0x64c4
80 #define AVIVO_DC_LUTA_BLACK_OFFSET_GREEN 0x64c8
81 #define AVIVO_DC_LUTA_BLACK_OFFSET_RED 0x64cc
82 #define AVIVO_DC_LUTA_WHITE_OFFSET_BLUE 0x64d0
83 #define AVIVO_DC_LUTA_WHITE_OFFSET_GREEN 0x64d4
84 #define AVIVO_DC_LUTA_WHITE_OFFSET_RED 0x64d8
86 #define AVIVO_DC_LUTB_CONTROL 0x6cc0
87 #define AVIVO_DC_LUTB_BLACK_OFFSET_BLUE 0x6cc4
88 #define AVIVO_DC_LUTB_BLACK_OFFSET_GREEN 0x6cc8
89 #define AVIVO_DC_LUTB_BLACK_OFFSET_RED 0x6ccc
90 #define AVIVO_DC_LUTB_WHITE_OFFSET_BLUE 0x6cd0
91 #define AVIVO_DC_LUTB_WHITE_OFFSET_GREEN 0x6cd4
92 #define AVIVO_DC_LUTB_WHITE_OFFSET_RED 0x6cd8
107 u32 cr = red >> (16 - info->
var.red.length);
108 u32 cg = green >> (16 - info->
var.green.length);
109 u32 cb = blue >> (16 - info->
var.blue.length);
115 value = (cr << info->
var.red.offset) |
116 (cg << info->
var.green.offset) |
117 (cb << info->
var.blue.offset);
118 if (info->
var.transp.length > 0) {
119 u32 mask = (1 << info->
var.transp.length) - 1;
120 mask <<= info->
var.transp.offset;
152 (red << 16 | green << 8 | blue));
169 (red << 16 | green << 8 | blue));
175 writel(((red) << 22) | ((green) << 12) | ((blue) << 2),
179 writel(((red) << 22) | ((green) << 12) | ((blue) << 2),
191 static int offb_blank(
int blank,
struct fb_info *
info)
206 for (i = 0; i < 256; i++) {
210 for (
j = 0;
j < 3;
j++)
252 static int offb_set_par(
struct fb_info *info)
282 static void offb_destroy(
struct fb_info *info)
290 static struct fb_ops offb_ops = {
292 .fb_destroy = offb_destroy,
293 .fb_setcolreg = offb_setcolreg,
294 .fb_set_par = offb_set_par,
295 .fb_blank = offb_blank,
308 addrp = of_get_pci_address(np, index, &asize, &flags);
315 if ((offset + size) > asize)
318 if (taddr == OF_BAD_ADDR)
320 return ioremap(taddr + offset, size);
328 if (dp && !
strncmp(name,
"ATY,Rage128", 11)) {
329 par->
cmap_adr = offb_map_reg(dp, 2, 0, 0x1fff);
332 }
else if (dp && (!
strncmp(name,
"ATY,RageM3pA", 12)
333 || !
strncmp(name,
"ATY,RageM3p12A", 14))) {
334 par->
cmap_adr = offb_map_reg(dp, 2, 0, 0x1fff);
337 }
else if (dp && !
strncmp(name,
"ATY,RageM3pB", 12)) {
338 par->
cmap_adr = offb_map_reg(dp, 2, 0, 0x1fff);
341 }
else if (dp && !
strncmp(name,
"ATY,Rage6", 9)) {
342 par->
cmap_adr = offb_map_reg(dp, 1, 0, 0x1fff);
345 }
else if (!
strncmp(name,
"ATY,", 4)) {
346 unsigned long base = address & 0xff000000
UL;
348 ioremap(base + 0x7ff000, 0x1000) + 0xcc0;
353 par->
cmap_adr = offb_map_reg(dp, 0, 0x6000, 0x1000);
356 }
else if (dp && !
strncmp(name,
"vga,Display-", 12)) {
363 if (vid && did && *vid == 0x1002 &&
364 ((*did >= 0x7100 && *did < 0x7800) ||
366 par->
cmap_adr = offb_map_reg(pciparent, 2, 0, 0x10000);
370 of_node_put(pciparent);
372 const u32 io_of_addr[3] = { 0x01000000, 0x0, 0x0 };
374 if (io_addr != OF_BAD_ADDR) {
386 static void __init offb_init_fb(
const char *name,
const char *
full_name,
388 int pitch,
unsigned long address,
393 unsigned long res_start =
address;
402 "Using unsupported %dx%d %s at %lx, depth=%d, pitch=%d\n",
403 width, height, name, address, depth, pitch);
404 if (depth != 8 && depth != 15 && depth != 16 && depth != 32) {
423 strncat(fix->
id, name,
sizeof(fix->
id) -
sizeof(
"OFfb "));
424 fix->
id[
sizeof(fix->
id) - 1] =
'\0';
437 offb_init_palette_hacks(info, dp, name, address);
447 var->
green.offset = 0;
448 var->
green.length = 8;
449 var->
blue.offset = 0;
450 var->
blue.length = 8;
456 var->
red.offset = 10;
458 var->
green.offset = 5;
459 var->
green.length = 5;
460 var->
blue.offset = 0;
461 var->
blue.length = 5;
467 var->
red.offset = 11;
469 var->
green.offset = 5;
470 var->
green.length = 6;
471 var->
blue.offset = 0;
472 var->
blue.length = 5;
478 var->
red.offset = 16;
480 var->
green.offset = 8;
481 var->
green.length = 8;
482 var->
blue.offset = 0;
483 var->
blue.length = 8;
488 var->
red.msb_right = var->
green.msb_right = var->
blue.msb_right =
489 var->
transp.msb_right = 0;
508 info->
fbops = &offb_ops;
519 info->
node, full_name);
535 int i, width = 640, height = 480, depth = 8, pitch = 640;
536 unsigned int flags, rsize, addr_prop = 0;
538 u64 rstart, address = OF_BAD_ADDR;
541 int foreign_endian = 0;
554 if (pp && len ==
sizeof(
u32))
560 if (pp && len ==
sizeof(
u32))
566 if (pp && len ==
sizeof(
u32))
572 if (pp && len ==
sizeof(
u32) && (*pp != 0xffffffffu))
575 pitch = width * ((depth + 7) / 8);
577 rsize = (
unsigned long)pitch * (
unsigned long)
height;
592 if (up && len ==
sizeof(
u32))
608 if (rstart == OF_BAD_ADDR)
610 if (addr_prop && (rstart <= addr_prop) &&
611 ((rstart + asize) >= (addr_prop + rsize)))
617 if (rsize > max_size) {
619 address = OF_BAD_ADDR;
622 if (address == OF_BAD_ADDR)
626 if (address == OF_BAD_ADDR && addr_prop)
627 address = (
u64)addr_prop;
628 if (address != OF_BAD_ADDR) {
632 offb_init_fb(no_real_node ?
"bootx" : dp->
name,
633 no_real_node ?
"display" : dp->
full_name,
634 width, height, depth, pitch, address,
635 foreign_endian, no_real_node ?
NULL : dp);
639 static int __init offb_init(
void)
661 offb_init_nodriver(dp, 0);
667 offb_init_nodriver(dp, 0);