Subject: [PATCH 1/4] viafb: rework color checking

viafb: rework color checking

This patch makes color checking a bit more tolerant in what values it
allows and more fine grained to later support 15 and 30 bits formats.
It splits the filling of the color information in var to a seperate
function and sets some color related values in var that where previously
untouched.
This could be a bug fix but at least I don't know any applications that
was fooled by not correctly setting the fields in var. At least no
regressions are expected.

Signed-off-by: Florian Tobias Schandinat <[email protected]>
---
drivers/video/via/hw.c | 30 --------------------
drivers/video/via/viafbdev.c | 63 ++++++++++++++++++++++++++++++++++++++----
2 files changed, 57 insertions(+), 36 deletions(-)

diff --git a/drivers/video/via/hw.c b/drivers/video/via/hw.c
index ed8d78a..47d9024 100644
--- a/drivers/video/via/hw.c
+++ b/drivers/video/via/hw.c
@@ -2622,36 +2622,6 @@ void viafb_fill_var_timing_info(struct fb_var_screeninfo *var, int refresh,
}

crt_reg = crt_timing[index].crtc;
- switch (var->bits_per_pixel) {
- case 8:
- var->red.offset = 0;
- var->green.offset = 0;
- var->blue.offset = 0;
- var->red.length = 6;
- var->green.length = 6;
- var->blue.length = 6;
- break;
- case 16:
- var->red.offset = 11;
- var->green.offset = 5;
- var->blue.offset = 0;
- var->red.length = 5;
- var->green.length = 6;
- var->blue.length = 5;
- break;
- case 32:
- var->red.offset = 16;
- var->green.offset = 8;
- var->blue.offset = 0;
- var->red.length = 8;
- var->green.length = 8;
- var->blue.length = 8;
- break;
- default:
- /* never happed, put here to keep consistent */
- break;
- }
-
var->pixclock = viafb_get_pixclock(var->xres, var->yres, refresh);
var->left_margin =
crt_reg.hor_total - (crt_reg.hor_sync_start + crt_reg.hor_sync_end);
diff --git a/drivers/video/via/viafbdev.c b/drivers/video/via/viafbdev.c
index bb0f616..bd8db75 100644
--- a/drivers/video/via/viafbdev.c
+++ b/drivers/video/via/viafbdev.c
@@ -60,6 +60,47 @@ static int viafb_pan_display(struct fb_var_screeninfo *var,
static struct fb_ops viafb_ops;


+static void viafb_fill_var_color_info(struct fb_var_screeninfo *var, u8 depth)
+{
+ var->grayscale = 0;
+ var->red.msb_right = 0;
+ var->green.msb_right = 0;
+ var->blue.msb_right = 0;
+ var->transp.offset = 0;
+ var->transp.length = 0;
+ var->transp.msb_right = 0;
+ var->nonstd = 0;
+ switch (depth) {
+ case 8:
+ var->bits_per_pixel = 8;
+ var->red.offset = 0;
+ var->green.offset = 0;
+ var->blue.offset = 0;
+ var->red.length = 6;
+ var->green.length = 6;
+ var->blue.length = 6;
+ break;
+ case 16:
+ var->bits_per_pixel = 16;
+ var->red.offset = 11;
+ var->green.offset = 5;
+ var->blue.offset = 0;
+ var->red.length = 5;
+ var->green.length = 6;
+ var->blue.length = 5;
+ break;
+ case 24:
+ var->bits_per_pixel = 32;
+ var->red.offset = 16;
+ var->green.offset = 8;
+ var->blue.offset = 0;
+ var->red.length = 8;
+ var->green.length = 8;
+ var->blue.length = 8;
+ break;
+ }
+}
+
static void viafb_update_fix(struct fb_info *info)
{
u32 bpp = info->var.bits_per_pixel;
@@ -81,6 +122,7 @@ static void viafb_setup_fixinfo(struct fb_fix_screeninfo *fix,

fix->type = FB_TYPE_PACKED_PIXELS;
fix->type_aux = 0;
+ fix->visual = FB_VISUAL_TRUECOLOR;

fix->xpanstep = fix->ywrapstep = 0;
fix->ypanstep = 1;
@@ -103,7 +145,7 @@ static int viafb_release(struct fb_info *info, int user)
static int viafb_check_var(struct fb_var_screeninfo *var,
struct fb_info *info)
{
- int htotal, vtotal;
+ int htotal, vtotal, depth;
struct VideoModeTable *vmode_entry;
struct viafb_par *ppar = info->par;
u32 long_refresh;
@@ -122,13 +164,22 @@ static int viafb_check_var(struct fb_var_screeninfo *var,
return -EINVAL;
}

- if (24 == var->bits_per_pixel)
- var->bits_per_pixel = 32;
+ depth = fb_get_color_depth(var, &info->fix);
+ if (!depth)
+ depth = var->bits_per_pixel;

- if (var->bits_per_pixel != 8 && var->bits_per_pixel != 16 &&
- var->bits_per_pixel != 32)
+ if (depth < 0 || depth > 32)
return -EINVAL;
+ else if (!depth)
+ depth = 24;
+ else if (depth <= 8)
+ depth = 8;
+ else if (depth <= 16)
+ depth = 16;
+ else
+ depth = 24;

+ viafb_fill_var_color_info(var, depth);
if ((var->xres_virtual * (var->bits_per_pixel >> 3)) & 0x1F)
/*32 pixel alignment */
var->xres_virtual = (var->xres_virtual + 31) & ~31;
--
1.6.3.2


Subject: [PATCH 2/4] viafb: some virtual_xres handling fixes

viafb: some virtual_xres handling fixes

Do not require the virtual_xres to be aligned as line length is for
such purposes. Calculate always the smallest line length required.

Signed-off-by: Florian Tobias Schandinat <[email protected]>
---
drivers/video/via/viafbdev.c | 12 ++++--------
1 files changed, 4 insertions(+), 8 deletions(-)

diff --git a/drivers/video/via/viafbdev.c b/drivers/video/via/viafbdev.c
index bd8db75..0fe748d 100644
--- a/drivers/video/via/viafbdev.c
+++ b/drivers/video/via/viafbdev.c
@@ -107,8 +107,7 @@ static void viafb_update_fix(struct fb_info *info)

info->fix.visual =
bpp == 8 ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR;
- info->fix.line_length =
- ((info->var.xres_virtual + 7) & ~7) * bpp / 8;
+ info->fix.line_length = (info->var.xres_virtual * bpp / 8 + 7) & ~7;
}

static void viafb_setup_fixinfo(struct fb_fix_screeninfo *fix,
@@ -148,7 +147,7 @@ static int viafb_check_var(struct fb_var_screeninfo *var,
int htotal, vtotal, depth;
struct VideoModeTable *vmode_entry;
struct viafb_par *ppar = info->par;
- u32 long_refresh;
+ u32 long_refresh, line;

DEBUG_MSG(KERN_INFO "viafb_check_var!\n");
/* Sanity check */
@@ -180,11 +179,8 @@ static int viafb_check_var(struct fb_var_screeninfo *var,
depth = 24;

viafb_fill_var_color_info(var, depth);
- if ((var->xres_virtual * (var->bits_per_pixel >> 3)) & 0x1F)
- /*32 pixel alignment */
- var->xres_virtual = (var->xres_virtual + 31) & ~31;
- if (var->xres_virtual * var->yres_virtual * var->bits_per_pixel / 8 >
- ppar->memsize)
+ line = (var->xres_virtual * var->bits_per_pixel / 8 + 7) & ~7;
+ if (line * var->yres_virtual > ppar->memsize)
return -EINVAL;

/* Based on var passed in to calculate the refresh,
--
1.6.3.2

Subject: [PATCH 4/4] viafb: support color depth 15 and 30

viafb: support color depth 15 and 30

This patch adds support for the color depth 15 on IGA1 and 30 on
IGA1 and IGA2. To allow the usage of those the driver now refuses
color depth that are totally off and otherwise the selection in
viafb_check_var is used. Therefore the first call to this for the
first framebuffer was delayed a bit. It only enables the new formats
if they are requested exactly (viafb_bpp=15|30).
As this is a new feature, no regressions are expected. The color
depth 15 was successfully tested. Didn't get anything usable for 30
but that might be the programs fault. I would like to get some
feedback whether it works as expected or not if somebody knows a
program/configuration where it should.

Signed-off-by: Florian Tobias Schandinat <[email protected]>
---
drivers/video/via/hw.c | 9 ++++++++
drivers/video/via/viafbdev.c | 43 ++++++++++++++++++++++++-----------------
2 files changed, 34 insertions(+), 18 deletions(-)

diff --git a/drivers/video/via/hw.c b/drivers/video/via/hw.c
index 1823253..f2583b1 100644
--- a/drivers/video/via/hw.c
+++ b/drivers/video/via/hw.c
@@ -694,12 +694,18 @@ void viafb_set_primary_color_depth(u8 depth)
case 8:
value = 0x00;
break;
+ case 15:
+ value = 0x04;
+ break;
case 16:
value = 0x14;
break;
case 24:
value = 0x0C;
break;
+ case 30:
+ value = 0x08;
+ break;
default:
printk(KERN_WARNING "viafb_set_primary_color_depth: "
"Unsupported depth: %d\n", depth);
@@ -724,6 +730,9 @@ void viafb_set_secondary_color_depth(u8 depth)
case 24:
value = 0xC0;
break;
+ case 30:
+ value = 0x80;
+ break;
default:
printk(KERN_WARNING "viafb_set_secondary_color_depth: "
"Unsupported depth: %d\n", depth);
diff --git a/drivers/video/via/viafbdev.c b/drivers/video/via/viafbdev.c
index 410de33..ce7783b 100644
--- a/drivers/video/via/viafbdev.c
+++ b/drivers/video/via/viafbdev.c
@@ -80,6 +80,15 @@ static void viafb_fill_var_color_info(struct fb_var_screeninfo *var, u8 depth)
var->green.length = 8;
var->blue.length = 8;
break;
+ case 15:
+ var->bits_per_pixel = 16;
+ var->red.offset = 10;
+ var->green.offset = 5;
+ var->blue.offset = 0;
+ var->red.length = 5;
+ var->green.length = 5;
+ var->blue.length = 5;
+ break;
case 16:
var->bits_per_pixel = 16;
var->red.offset = 11;
@@ -98,6 +107,15 @@ static void viafb_fill_var_color_info(struct fb_var_screeninfo *var, u8 depth)
var->green.length = 8;
var->blue.length = 8;
break;
+ case 30:
+ var->bits_per_pixel = 32;
+ var->red.offset = 20;
+ var->green.offset = 10;
+ var->blue.offset = 0;
+ var->red.length = 10;
+ var->green.length = 10;
+ var->blue.length = 10;
+ break;
}
}

@@ -171,6 +189,10 @@ static int viafb_check_var(struct fb_var_screeninfo *var,
return -EINVAL;
else if (!depth)
depth = 24;
+ else if (depth == 15 && viafb_dual_fb && ppar->iga_path == IGA1)
+ depth = 15;
+ else if (depth == 30)
+ depth = 30;
else if (depth <= 8)
depth = 8;
else if (depth <= 16)
@@ -1811,19 +1833,6 @@ static int __devinit via_pci_probe(struct pci_dev *pdev,
viafb_second_virtual_yres = viafb_second_yres;
}

- switch (viafb_bpp) {
- case 0 ... 8:
- viafb_bpp = 8;
- break;
- case 9 ... 16:
- viafb_bpp = 16;
- break;
- case 17 ... 32:
- viafb_bpp = 32;
- break;
- default:
- viafb_bpp = 8;
- }
default_var.xres = default_xres;
default_var.yres = default_yres;
switch (default_xres) {
@@ -1836,8 +1845,6 @@ static int __devinit via_pci_probe(struct pci_dev *pdev,
}
default_var.yres_virtual = default_yres;
default_var.bits_per_pixel = viafb_bpp;
- if (default_var.bits_per_pixel == 15)
- default_var.bits_per_pixel = 16;
default_var.pixclock =
viafb_get_pixclock(default_xres, default_yres, viafb_refresh);
default_var.left_margin = (default_xres >> 3) & 0xf8;
@@ -1847,7 +1854,6 @@ static int __devinit via_pci_probe(struct pci_dev *pdev,
default_var.hsync_len = default_var.left_margin;
default_var.vsync_len = 4;
viafb_setup_fixinfo(&viafbinfo->fix, viaparinfo);
- viafb_check_var(&default_var, viafbinfo);
viafbinfo->var = default_var;

if (viafb_dual_fb) {
@@ -1883,8 +1889,6 @@ static int __devinit via_pci_probe(struct pci_dev *pdev,
default_var.yres = viafb_second_yres;
default_var.xres_virtual = viafb_second_virtual_xres;
default_var.yres_virtual = viafb_second_virtual_yres;
- if (viafb_bpp1 != viafb_bpp)
- viafb_bpp1 = viafb_bpp;
default_var.bits_per_pixel = viafb_bpp1;
default_var.pixclock =
viafb_get_pixclock(viafb_second_xres, viafb_second_yres,
@@ -1904,6 +1908,7 @@ static int __devinit via_pci_probe(struct pci_dev *pdev,
&viafbinfo1->fix);
}

+ viafb_check_var(&viafbinfo->var, viafbinfo);
viafb_update_fix(viafbinfo);
viaparinfo->depth = fb_get_color_depth(&viafbinfo->var,
&viafbinfo->fix);
@@ -2070,6 +2075,8 @@ static int __init viafb_init(void)
#endif
if (parse_mode(viafb_mode, &dummy, &dummy)
|| parse_mode(viafb_mode1, &dummy, &dummy)
+ || viafb_bpp < 0 || viafb_bpp > 32
+ || viafb_bpp1 < 0 || viafb_bpp1 > 32
|| parse_active_dev())
return -EINVAL;

--
1.6.3.2

Subject: [PATCH 3/4] viafb: rework color setting

viafb: rework color setting

This is a rewritten version of viafb_setcolreg. The hardware register
writes were split up and moved to hw.c where they belong as this is
really low level stuff. It was made dual fb aware.
Furthermore viafb_setcmap was removed as the problem with 8bpp
originated from a bug in writing multiple color registers at once.
The removal of viafb_setcmap might introduce a small performance
regression but its certainly better to receive the correct result a
bit slower than a garbled picture fast. It should give us a working
8bpp mode and is more extensible than the old hardcoded code. No
other regressions are expected but as the hardware might be a bit
picky it might cause some regressions in 8bpp mode on some hardware
although I doubt that.

Signed-off-by: Florian Tobias Schandinat <[email protected]>
---
drivers/video/via/hw.c | 28 ++++-
drivers/video/via/hw.h | 2 +
drivers/video/via/viafbdev.c | 237 +++++-------------------------------------
3 files changed, 51 insertions(+), 216 deletions(-)

diff --git a/drivers/video/via/hw.c b/drivers/video/via/hw.c
index 47d9024..1823253 100644
--- a/drivers/video/via/hw.c
+++ b/drivers/video/via/hw.c
@@ -691,7 +691,7 @@ void viafb_set_primary_color_depth(u8 depth)

DEBUG_MSG(KERN_DEBUG "viafb_set_primary_color_depth(%d)\n", depth);
switch (depth) {
- case 6:
+ case 8:
value = 0x00;
break;
case 16:
@@ -715,7 +715,7 @@ void viafb_set_secondary_color_depth(u8 depth)

DEBUG_MSG(KERN_DEBUG "viafb_set_secondary_color_depth(%d)\n", depth);
switch (depth) {
- case 6:
+ case 8:
value = 0x00;
break;
case 16:
@@ -733,6 +733,27 @@ void viafb_set_secondary_color_depth(u8 depth)
viafb_write_reg_mask(0x67, VIACR, value, 0xC0);
}

+static void set_color_register(u8 index, u8 red, u8 green, u8 blue)
+{
+ outb(0xFF, 0x3C6); /* bit mask of palette */
+ outb(index, 0x3C8);
+ outb(red, 0x3C9);
+ outb(green, 0x3C9);
+ outb(blue, 0x3C9);
+}
+
+void viafb_set_primary_color_register(u8 index, u8 red, u8 green, u8 blue)
+{
+ viafb_write_reg_mask(0x1A, VIASR, 0x00, 0x01);
+ set_color_register(index, red, green, blue);
+}
+
+void viafb_set_secondary_color_register(u8 index, u8 red, u8 green, u8 blue)
+{
+ viafb_write_reg_mask(0x1A, VIASR, 0x01, 0x01);
+ set_color_register(index, red, green, blue);
+}
+
void viafb_set_output_path(int device, int set_iga, int output_interface)
{
switch (device) {
@@ -2210,8 +2231,7 @@ int viafb_setmode(struct VideoModeTable *vmode_tbl, int video_bpp,
outb(VPIT.SR[i - 1], VIASR + 1);
}

- viafb_write_reg_mask(0x15, VIASR, viafbinfo->fix.visual
- == FB_VISUAL_PSEUDOCOLOR ? 0x22 : 0xA2, 0xA2);
+ viafb_write_reg_mask(0x15, VIASR, 0xA2, 0xA2);
viafb_set_iga_path();

/* Write CRTC */
diff --git a/drivers/video/via/hw.h b/drivers/video/via/hw.h
index 691fbd2..12ef32d 100644
--- a/drivers/video/via/hw.h
+++ b/drivers/video/via/hw.h
@@ -914,6 +914,8 @@ void viafb_set_primary_address(u32 addr);
void viafb_set_secondary_address(u32 addr);
void viafb_set_primary_pitch(u32 pitch);
void viafb_set_secondary_pitch(u32 pitch);
+void viafb_set_primary_color_register(u8 index, u8 red, u8 green, u8 blue);
+void viafb_set_secondary_color_register(u8 index, u8 red, u8 green, u8 blue);
void viafb_get_fb_info(unsigned int *fb_base, unsigned int *fb_len);

#endif /* __HW_H__ */
diff --git a/drivers/video/via/viafbdev.c b/drivers/video/via/viafbdev.c
index 0fe748d..410de33 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)
var->red.offset = 0;
var->green.offset = 0;
var->blue.offset = 0;
- var->red.length = 6;
- var->green.length = 6;
- var->blue.length = 6;
+ var->red.length = 8;
+ var->green.length = 8;
+ var->blue.length = 8;
break;
case 16:
var->bits_per_pixel = 16;
@@ -255,219 +255,33 @@ static int viafb_set_par(struct fb_info *info)
static int viafb_setcolreg(unsigned regno, unsigned red, unsigned green,
unsigned blue, unsigned transp, struct fb_info *info)
{
- u8 sr1a, sr1b, cr67, cr6a, rev = 0, shift = 10;
- unsigned cmap_entries = (info->var.bits_per_pixel == 8) ? 256 : 16;
- DEBUG_MSG(KERN_INFO "viafb_setcolreg!\n");
- if (regno >= cmap_entries)
- return 1;
- if (UNICHROME_CLE266 == viaparinfo->chip_info->gfx_chip_name) {
- /*
- * Read PCI bus 0,dev 0,function 0,index 0xF6 to get chip rev.
- */
- outl(0x80000000 | (0xf6 & ~3), (unsigned long)0xCF8);
- rev = (inl((unsigned long)0xCFC) >> ((0xf6 & 3) * 8)) & 0xff;
- }
- switch (info->var.bits_per_pixel) {
- case 8:
- outb(0x1A, 0x3C4);
- sr1a = inb(0x3C5);
- outb(0x1B, 0x3C4);
- sr1b = inb(0x3C5);
- outb(0x67, 0x3D4);
- cr67 = inb(0x3D5);
- outb(0x6A, 0x3D4);
- cr6a = inb(0x3D5);
-
- /* Map the 3C6/7/8/9 to the IGA2 */
- outb(0x1A, 0x3C4);
- outb(sr1a | 0x01, 0x3C5);
- /* Second Display Engine colck always on */
- outb(0x1B, 0x3C4);
- outb(sr1b | 0x80, 0x3C5);
- /* Second Display Color Depth 8 */
- outb(0x67, 0x3D4);
- outb(cr67 & 0x3F, 0x3D5);
- outb(0x6A, 0x3D4);
- /* Second Display Channel Reset CR6A[6]) */
- outb(cr6a & 0xBF, 0x3D5);
- /* Second Display Channel Enable CR6A[7] */
- outb(cr6a | 0x80, 0x3D5);
- /* Second Display Channel stop reset) */
- outb(cr6a | 0x40, 0x3D5);
-
- /* Bit mask of palette */
- outb(0xFF, 0x3c6);
- /* Write one register of IGA2 */
- outb(regno, 0x3C8);
- if (UNICHROME_CLE266 == viaparinfo->chip_info->gfx_chip_name &&
- rev >= 15) {
- shift = 8;
- viafb_write_reg_mask(CR6A, VIACR, BIT5, BIT5);
- viafb_write_reg_mask(SR15, VIASR, BIT7, BIT7);
- } else {
- shift = 10;
- viafb_write_reg_mask(CR6A, VIACR, 0, BIT5);
- viafb_write_reg_mask(SR15, VIASR, 0, BIT7);
- }
- outb(red >> shift, 0x3C9);
- outb(green >> shift, 0x3C9);
- outb(blue >> shift, 0x3C9);
-
- /* Map the 3C6/7/8/9 to the IGA1 */
- outb(0x1A, 0x3C4);
- outb(sr1a & 0xFE, 0x3C5);
- /* Bit mask of palette */
- outb(0xFF, 0x3c6);
- /* Write one register of IGA1 */
- outb(regno, 0x3C8);
- outb(red >> shift, 0x3C9);
- outb(green >> shift, 0x3C9);
- outb(blue >> shift, 0x3C9);
-
- outb(0x1A, 0x3C4);
- outb(sr1a, 0x3C5);
- outb(0x1B, 0x3C4);
- outb(sr1b, 0x3C5);
- outb(0x67, 0x3D4);
- outb(cr67, 0x3D5);
- outb(0x6A, 0x3D4);
- outb(cr6a, 0x3D5);
- break;
- case 16:
- ((u32 *) info->pseudo_palette)[regno] = (red & 0xF800) |
- ((green & 0xFC00) >> 5) | ((blue & 0xF800) >> 11);
- break;
- case 32:
- ((u32 *) info->pseudo_palette)[regno] =
- ((transp & 0xFF00) << 16) |
- ((red & 0xFF00) << 8) |
- ((green & 0xFF00)) | ((blue & 0xFF00) >> 8);
- break;
- }
-
- return 0;
+ struct viafb_par *viapar = info->par;
+ u32 r, g, b;

-}
+ if (info->fix.visual == FB_VISUAL_PSEUDOCOLOR) {
+ if (regno > 255)
+ return -EINVAL;

-/*CALLED BY: fb_set_cmap */
-/* fb_set_var, pass 256 colors */
-/*CALLED BY: fb_set_cmap */
-/* fbcon_set_palette, pass 16 colors */
-static int viafb_setcmap(struct fb_cmap *cmap, struct fb_info *info)
-{
- u32 len = cmap->len;
- u32 i;
- u16 *pred = cmap->red;
- u16 *pgreen = cmap->green;
- u16 *pblue = cmap->blue;
- u16 *ptransp = cmap->transp;
- u8 sr1a, sr1b, cr67, cr6a, rev = 0, shift = 10;
- if (len > 256)
- return 1;
- if (UNICHROME_CLE266 == viaparinfo->chip_info->gfx_chip_name) {
- /*
- * Read PCI bus 0, dev 0, function 0, index 0xF6 to get chip
- * rev.
- */
- outl(0x80000000 | (0xf6 & ~3), (unsigned long)0xCF8);
- rev = (inl((unsigned long)0xCFC) >> ((0xf6 & 3) * 8)) & 0xff;
- }
- switch (info->var.bits_per_pixel) {
- case 8:
- outb(0x1A, 0x3C4);
- sr1a = inb(0x3C5);
- outb(0x1B, 0x3C4);
- sr1b = inb(0x3C5);
- outb(0x67, 0x3D4);
- cr67 = inb(0x3D5);
- outb(0x6A, 0x3D4);
- cr6a = inb(0x3D5);
- /* Map the 3C6/7/8/9 to the IGA2 */
- outb(0x1A, 0x3C4);
- outb(sr1a | 0x01, 0x3C5);
- outb(0x1B, 0x3C4);
- /* Second Display Engine colck always on */
- outb(sr1b | 0x80, 0x3C5);
- outb(0x67, 0x3D4);
- /* Second Display Color Depth 8 */
- outb(cr67 & 0x3F, 0x3D5);
- outb(0x6A, 0x3D4);
- /* Second Display Channel Reset CR6A[6]) */
- outb(cr6a & 0xBF, 0x3D5);
- /* Second Display Channel Enable CR6A[7] */
- outb(cr6a | 0x80, 0x3D5);
- /* Second Display Channel stop reset) */
- outb(cr6a | 0xC0, 0x3D5);
-
- /* Bit mask of palette */
- outb(0xFF, 0x3c6);
- outb(0x00, 0x3C8);
- if (UNICHROME_CLE266 == viaparinfo->chip_info->gfx_chip_name &&
- rev >= 15) {
- shift = 8;
- viafb_write_reg_mask(CR6A, VIACR, BIT5, BIT5);
- viafb_write_reg_mask(SR15, VIASR, BIT7, BIT7);
- } else {
- shift = 10;
- viafb_write_reg_mask(CR6A, VIACR, 0, BIT5);
- viafb_write_reg_mask(SR15, VIASR, 0, BIT7);
- }
- for (i = 0; i < len; i++) {
- outb((*(pred + i)) >> shift, 0x3C9);
- outb((*(pgreen + i)) >> shift, 0x3C9);
- outb((*(pblue + i)) >> shift, 0x3C9);
- }
+ if (!viafb_dual_fb || viapar->iga_path == IGA1)
+ viafb_set_primary_color_register(regno, red >> 8,
+ green >> 8, blue >> 8);

- outb(0x1A, 0x3C4);
- /* Map the 3C6/7/8/9 to the IGA1 */
- outb(sr1a & 0xFE, 0x3C5);
- /* Bit mask of palette */
- outb(0xFF, 0x3c6);
- outb(0x00, 0x3C8);
- for (i = 0; i < len; i++) {
- outb((*(pred + i)) >> shift, 0x3C9);
- outb((*(pgreen + i)) >> shift, 0x3C9);
- outb((*(pblue + i)) >> shift, 0x3C9);
- }
+ if (!viafb_dual_fb || viapar->iga_path == IGA2)
+ viafb_set_secondary_color_register(regno, red >> 8,
+ green >> 8, blue >> 8);
+ } else {
+ if (regno > 15)
+ return -EINVAL;

- outb(0x1A, 0x3C4);
- outb(sr1a, 0x3C5);
- outb(0x1B, 0x3C4);
- outb(sr1b, 0x3C5);
- outb(0x67, 0x3D4);
- outb(cr67, 0x3D5);
- outb(0x6A, 0x3D4);
- outb(cr6a, 0x3D5);
- break;
- case 16:
- if (len > 17)
- return 0; /* Because static u32 pseudo_pal[17]; */
- for (i = 0; i < len; i++)
- ((u32 *) info->pseudo_palette)[i] =
- (*(pred + i) & 0xF800) |
- ((*(pgreen + i) & 0xFC00) >> 5) |
- ((*(pblue + i) & 0xF800) >> 11);
- break;
- case 32:
- if (len > 17)
- return 0;
- if (ptransp) {
- for (i = 0; i < len; i++)
- ((u32 *) info->pseudo_palette)[i] =
- ((*(ptransp + i) & 0xFF00) << 16) |
- ((*(pred + i) & 0xFF00) << 8) |
- ((*(pgreen + i) & 0xFF00)) |
- ((*(pblue + i) & 0xFF00) >> 8);
- } else {
- for (i = 0; i < len; i++)
- ((u32 *) info->pseudo_palette)[i] =
- 0x00000000 |
- ((*(pred + i) & 0xFF00) << 8) |
- ((*(pgreen + i) & 0xFF00)) |
- ((*(pblue + i) & 0xFF00) >> 8);
- }
- break;
+ r = (red >> (16 - info->var.red.length))
+ << info->var.red.offset;
+ b = (blue >> (16 - info->var.blue.length))
+ << info->var.blue.offset;
+ g = (green >> (16 - info->var.green.length))
+ << info->var.green.offset;
+ ((u32 *) info->pseudo_palette)[regno] = r | g | b;
}
+
return 0;
}

@@ -2286,7 +2100,6 @@ static struct fb_ops viafb_ops = {
.fb_cursor = viafb_cursor,
.fb_ioctl = viafb_ioctl,
.fb_sync = viafb_sync,
- .fb_setcmap = viafb_setcmap,
};

module_init(viafb_init);
--
1.6.3.2