linuxppc-dev.lists.ozlabs.org archive mirror
 help / color / mirror / Atom feed
* Re: [linux-fbdev] Re: r128 DRI driver now fully functional
@ 2001-01-31 20:29 Petr Vandrovec
  2001-02-02 15:00 ` Michel Dänzer
  0 siblings, 1 reply; 2+ messages in thread
From: Petr Vandrovec @ 2001-01-31 20:29 UTC (permalink / raw)
  To: Michel Daenzer; +Cc: andi, benh, linuxppc-dev, linux-fbdev, geert


On 31 Jan 01 at 19:53, Michel Dänzer wrote:
> > The disadvantage is that if you change the palette, the text colors don't
> > change until you redraw the screen (or switch VC back-and-forth). That's why
> > I decided to use the hardware palette in directcolor modes.
>
> I don't mind using the hardware palette if you (or anyone) tell me how to get
> RGB565 working with that. :)

It depends on how your hardware works:

If it uses palette entries 0-31 for R/B and 0-63 for G, program
dispsw_data pointed array (pseudo_palette) with

for (i = 0; i < 16; i++) arr[i] = i * ((1 << 11) | (1 << 5) | 1);

and your setcolreg should program r,g,b fields for regno register.

If your hardware uses entries 0,8,16,24...248 for R/B and
0,4,8,12,... for G, things are worse:

program pseudo_palette with same 'arr[i] = i * ((1 << 11) | (1 << 5) | 1);'

But setcolreg is much worse:

if (regno) {
  if (regno & 1) {
    oldR = oldB = 0;
  } else {
    outb(regno * 4, PALETTE_R_INDEX);
    oldR = inb(PALETTE_DATA);
    inb(PALETTE_DATA);
    oldG = inb(PALETTE_DATA);
  }
  outb(regno * 4, PALETTE_W_INDEX);
  outb(oldR, PALETTE_DATA);
  outb(g, PALETTE_DATA);
  outb(oldB, PALETTE_DATA);

  outb(regno * 8, PALETTE_R_INDEX);
  inb(PALETTE_DATA);
  oldG = inb(PALETTE_DATA);
  inb(PALETTE_DATA);
} else {
  oldG = g;
}
outb(regno * 8, PALETTE_W_INDEX);
outb(r, PALETTE_DATA);
outb(oldG, PALETTE_DATA);
outb(g, PALETTE_DATA);

I think that you should create 3x256 (or 3x64) array which will mirror
DAC state, as otherwise you have to do too many ops to set
one register...

Also do not forget that you must use only low 16 color registers (regno
on input to setcolreg) for text console, as others (16-31/16-63) are not
saved/restored by console palette handling code.
                                            Best regards,
                                                Petr Vandrovec
                                                vandrove@vc.cvut.cz


** Sent via the linuxppc-dev mail list. See http://lists.linuxppc.org/

^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: [linux-fbdev] Re: r128 DRI driver now fully functional
  2001-01-31 20:29 [linux-fbdev] Re: r128 DRI driver now fully functional Petr Vandrovec
@ 2001-02-02 15:00 ` Michel Dänzer
  0 siblings, 0 replies; 2+ messages in thread
From: Michel Dänzer @ 2001-02-02 15:00 UTC (permalink / raw)
  To: Brad Douglas
  Cc: Petr Vandrovec, andi, benh, linuxppc-dev, linux-fbdev, geert,
	Paul Mackerras

[-- Attachment #1: Type: text/plain, Size: 1824 bytes --]

Petr Vandrovec wrote:
>
> On 31 Jan 01 at 19:53, Michel Dänzer wrote:
> > > The disadvantage is that if you change the palette, the text colors
> > > don't change until you redraw the screen (or switch VC back-and-forth).
> > > That's why I decided to use the hardware palette in directcolor modes.
> >
> > I don't mind using the hardware palette if you (or anyone) tell me how to
> > get RGB565 working with that. :)
>
> It depends on how your hardware works:
>
> If it uses palette entries 0-31 for R/B and 0-63 for G, program
> dispsw_data pointed array (pseudo_palette) with
>
> for (i = 0; i < 16; i++) arr[i] = i * ((1 << 11) | (1 << 5) | 1);
>
> and your setcolreg should program r,g,b fields for regno register.
>
> If your hardware uses entries 0,8,16,24...248 for R/B and
> 0,4,8,12,... for G, things are worse:
>
> program pseudo_palette with same 'arr[i] = i * ((1 << 11) | (1 << 5) | 1);'
>
> But setcolreg is much worse:

[...]

Thanks Petr, that was the final hint. :)

The attached patch against 2.4.1 works for me, now I can use both 555 and 565
with aty128fb, so both depth 15 and 16 work in X with UseFBDev.


> I think that you should create 3x256 (or 3x64) array which will mirror
> DAC state, as otherwise you have to do too many ops to set
> one register...

Such an array was already present in aty128fb.


> Also do not forget that you must use only low 16 color registers (regno
> on input to setcolreg) for text console, as others (16-31/16-63) are not
> saved/restored by console palette handling code.

Does my patch handle this fine?


Looking forward to comments and suggestions. Andi, does this fix your color
problems in 16 bit?


--
Earthling Michel Dänzer (MrCooper)    \   Debian GNU/Linux (powerpc) developer
CS student, Free Software enthusiast   \        XFree86 and DRI project member

[-- Attachment #2: aty128fb-16bit.diff --]
[-- Type: text/plain, Size: 13783 bytes --]

--- drivers/video/aty128fb.c.orig	Sun Jan 14 03:53:57 2001
+++ drivers/video/aty128fb.c	Fri Feb  2 15:37:51 2001
@@ -251,7 +251,7 @@
     u32 offset, offset_cntl;
     u32 xoffset, yoffset;
     u32 vxres, vyres;
-    u32 bpp;
+    u32 depth, bpp;
 };

 struct aty128_pll {
@@ -379,7 +379,7 @@
 static void do_wait_for_fifo(u16 entries, struct fb_info_aty128 *info);
 static void wait_for_fifo(u16 entries, struct fb_info_aty128 *info);
 static void wait_for_idle(struct fb_info_aty128 *info);
-static u32 bpp_to_depth(u32 bpp);
+static u32 depth_to_dst(u32 depth);

 #ifdef FBCON_HAS_CFB8
 static struct display_switch fbcon_aty128_8;
@@ -698,7 +698,7 @@
 		GMC_SRC_CLIP_DEFAULT			|
 		GMC_DST_CLIP_DEFAULT			|
 		GMC_BRUSH_SOLIDCOLOR			|
-		(bpp_to_depth(par->crtc.bpp) << 8)	|
+		(depth_to_dst(par->crtc.depth) << 8)	|
 		GMC_SRC_DSTCOLOR			|
 		GMC_BYTE_ORDER_MSB_TO_LSB		|
 		GMC_DP_CONVERSION_TEMP_6500		|
@@ -731,17 +731,19 @@
 }


-/* convert bpp values to their register representation */
+/* convert depth values to their register representation */
 static u32
-bpp_to_depth(u32 bpp)
+depth_to_dst(u32 depth)
 {
-    if (bpp <= 8)
+    if (depth <= 8)
 	return DST_8BPP;
-    else if (bpp <= 16)
+    else if (depth <= 15)
         return DST_15BPP;
-    else if (bpp <= 24)
+    else if (depth == 16)
+        return DST_16BPP;
+    else if (depth <= 24)
 	return DST_24BPP;
-    else if (bpp <= 32)
+    else if (depth <= 32)
 	return DST_32BPP;

     return -EINVAL;
@@ -779,7 +781,7 @@
 			struct aty128_crtc *crtc,
 			const struct fb_info_aty128 *info)
 {
-    u32 xres, yres, vxres, vyres, xoffset, yoffset, bpp;
+    u32 xres, yres, vxres, vyres, xoffset, yoffset, bpp, dst;
     u32 left, right, upper, lower, hslen, vslen, sync, vmode;
     u32 h_total, h_disp, h_sync_strt, h_sync_wid, h_sync_pol;
     u32 v_total, v_disp, v_sync_strt, v_sync_wid, v_sync_pol, c_sync;
@@ -804,6 +806,11 @@
     sync  = var->sync;
     vmode = var->vmode;

+    if (bpp != 16)
+	depth = bpp;
+    else
+	depth = (var->green.length == 6) ? 16 : 15;
+
     /* check for mode eligibility
      * accept only non interlaced modes */
     if ((vmode & FB_VMODE_MASK) != FB_VMODE_NONINTERLACED)
@@ -819,17 +826,17 @@
     if (vyres < yres + yoffset)
 	vyres = yres + yoffset;

-    /* convert bpp into ATI register depth */
-    depth = bpp_to_depth(bpp);
+    /* convert depth into ATI register depth */
+    dst = depth_to_dst(depth);

     /* make sure we didn't get an invalid depth */
-    if (depth == -EINVAL) {
-        printk(KERN_ERR "aty128fb: Invalid depth\n");
+    if (dst == -EINVAL) {
+        printk(KERN_ERR "aty128fb: Invalid depth or RGBA\n");
         return -EINVAL;
     }

-    /* convert depth to bpp */
-    bytpp = mode_bytpp[depth];
+    /* convert register depth to bytes per pixel */
+    bytpp = mode_bytpp[dst];

     /* make sure there is enough video ram for the mode */
     if ((u32)(vxres * vyres * bytpp) > info->vram_size) {
@@ -870,7 +877,7 @@

     c_sync = sync & FB_SYNC_COMP_HIGH_ACT ? (1 << 4) : 0;

-    crtc->gen_cntl = 0x3000000L | c_sync | (depth << 8);
+    crtc->gen_cntl = 0x3000000L | c_sync | (dst << 8);

     crtc->h_total = h_total | (h_disp << 16);
     crtc->v_total = v_total | (v_disp << 16);
@@ -889,6 +896,7 @@
     crtc->vyres = vyres;
     crtc->xoffset = xoffset;
     crtc->yoffset = yoffset;
+    crtc->depth = depth;
     crtc->bpp = bpp;

     return 0;
@@ -896,7 +904,7 @@


 static int
-aty128_bpp_to_var(int pix_width, struct fb_var_screeninfo *var)
+aty128_pix_width_to_var(int pix_width, struct fb_var_screeninfo *var)
 {

     /* fill in pixel info */
@@ -913,7 +921,6 @@
 	var->transp.length = 0;
 	break;
     case CRTC_PIX_WIDTH_15BPP:
-    case CRTC_PIX_WIDTH_16BPP:
 	var->bits_per_pixel = 16;
 	var->red.offset = 10;
 	var->red.length = 5;
@@ -924,6 +931,17 @@
 	var->transp.offset = 0;
 	var->transp.length = 0;
 	break;
+    case CRTC_PIX_WIDTH_16BPP:
+	var->bits_per_pixel = 16;
+	var->red.offset = 11;
+	var->red.length = 5;
+	var->green.offset = 5;
+	var->green.length = 6;
+	var->blue.offset = 0;
+	var->blue.length = 5;
+	var->transp.offset = 0;
+	var->transp.length = 0;
+	break;
     case CRTC_PIX_WIDTH_24BPP:
         var->bits_per_pixel = 24;
         var->red.offset = 16;
@@ -992,7 +1010,7 @@
             (v_sync_pol ? 0 : FB_SYNC_VERT_HIGH_ACT) |
             (c_sync ? FB_SYNC_COMP_HIGH_ACT : 0);

-    aty128_bpp_to_var(pix_width, var);
+    aty128_pix_width_to_var(pix_width, var);

     var->xres = xres;
     var->yres = yres;
@@ -1117,7 +1135,7 @@
 static int
 aty128_ddafifo(struct aty128_ddafifo *dsp,
 		const struct aty128_pll *pll,
-		u32 bpp,
+		u32 depth,
 		const struct fb_info_aty128 *info)
 {
     const struct aty128_meminfo *m = info->mem;
@@ -1125,11 +1143,10 @@
     u32 fifo_width = info->constants.fifo_width;
     u32 fifo_depth = info->constants.fifo_depth;
     s32 x, b, p, ron, roff;
-    u32 n, d;
+    u32 n, d, bpp;

-    /* 15bpp is really 16bpp */
-    if (bpp == 15)
-	bpp = 16;
+    /* round up to multiple of 8 */
+    bpp = (depth+7) & ~7;

     n = xclk * fifo_width;
     d = pll->vclk * bpp;
@@ -1210,10 +1227,10 @@
     config = aty_ld_le32(CONFIG_CNTL) & ~3;

 #if defined(__BIG_ENDIAN)
-    if (par->crtc.bpp >= 24)
-	config |= 2;	/* make aperture do 32 byte swapping */
-    else if (par->crtc.bpp > 8)
-	config |= 1;	/* make aperture do 16 byte swapping */
+    if (par->crtc.bpp == 32)
+	config |= 2;	/* make aperture do 32 bit swapping */
+    else if (par->crtc.bpp == 16)
+	config |= 1;	/* make aperture do 16 bit swapping */
 #endif

     aty_st_le32(CONFIG_CNTL, config);
@@ -1268,7 +1285,7 @@
     if ((err = aty128_var_to_pll(var->pixclock, &par->pll, info)))
 	return err;

-    if ((err = aty128_ddafifo(&par->fifo_reg, &par->pll, par->crtc.bpp, info)))
+    if ((err = aty128_ddafifo(&par->fifo_reg, &par->pll, par->crtc.depth, info)))
 	return err;

     if (var->accel_flags & FB_ACCELF_TEXT)
@@ -1336,7 +1353,7 @@
     struct fb_info_aty128 *info = (struct fb_info_aty128 *)fb;
     struct aty128fb_par par;
     struct display *display;
-    int oldxres, oldyres, oldvxres, oldvyres, oldbpp, oldaccel;
+    int oldxres, oldyres, oldvxres, oldvyres, oldbpp, oldgreen, oldaccel;
     int accel, err;

     display = (con >= 0) ? &fb_display[con] : fb->disp;
@@ -1381,10 +1398,12 @@
     oldvxres = display->var.xres_virtual;
     oldvyres = display->var.yres_virtual;
     oldbpp = display->var.bits_per_pixel;
+    oldgreen = display->var.green.length;
     oldaccel = display->var.accel_flags;
     display->var = *var;
     if (oldxres != var->xres || oldyres != var->yres ||
 	oldvxres != var->xres_virtual || oldvyres != var->yres_virtual ||
+	oldgreen != var->green.length ||
 	oldbpp != var->bits_per_pixel || oldaccel != var->accel_flags) {

 	struct fb_fix_screeninfo fix;
@@ -1415,7 +1434,7 @@
     if (!info->fb_info.display_fg || info->fb_info.display_fg->vc_num == con)
 	aty128_set_par(&par, info);

-    if (oldbpp != var->bits_per_pixel) {
+    if (oldbpp != var->bits_per_pixel || oldgreen != var->green.length) {
 	if ((err = fb_alloc_cmap(&display->cmap, 0, 0)))
 	    return err;
 	do_install_cmap(con, &info->fb_info);
@@ -1436,7 +1455,6 @@
 	break;
 #endif
 #ifdef FBCON_HAS_CFB16
-    case 15:
     case 16:
 	disp->dispsw = accel ? &fbcon_aty128_16 : &fbcon_cfb16;
 	disp->dispsw_data = info->fbcon_cmap.cfb16;
@@ -1478,7 +1496,7 @@
     fix->type        = FB_TYPE_PACKED_PIXELS;
     fix->type_aux    = 0;
     fix->line_length = (par->crtc.vxres * par->crtc.bpp) >> 3;
-    fix->visual      = par->crtc.bpp <= 8 ? FB_VISUAL_PSEUDOCOLOR
+    fix->visual      = par->crtc.bpp == 8 ? FB_VISUAL_PSEUDOCOLOR
                                           : FB_VISUAL_DIRECTCOLOR;
     fix->ywrapstep = 0;
     fix->xpanstep  = 8;
@@ -1537,7 +1555,10 @@
     par->crtc.xoffset = xoffset;
     par->crtc.yoffset = yoffset;

-    offset = ((yoffset * par->crtc.vxres + xoffset) * par->crtc.bpp) >> 6;
+    offset = ((yoffset * par->crtc.vxres + xoffset)*(par->crtc.bpp >> 3)) & ~7;
+
+    if (par->crtc.bpp == 24)
+	offset += 8 * (offset % 3); /* Must be multiple of 8 and 3 */

     aty_st_le32(CRTC_OFFSET, offset);

@@ -1553,17 +1574,34 @@
 aty128fb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
 			struct fb_info *info)
 {
-#if 1
+#if 0
     fb_copy_cmap(&info->cmap, cmap, kspc ? 0 : 2);
 #else
-    struct fb_info_aty128 fb = (struct fb_info_aty128 *)info;
+    struct fb_info_aty128 *fb = (struct fb_info_aty128 *)info;

     if (con == fb->currcon) /* current console? */
 	return fb_get_cmap(cmap, kspc, aty128_getcolreg, info);
     else if (fb_display[con].cmap.len) /* non default colormap? */
 	fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2);
     else {
+#if 1
+	int size;
+
+	switch (fb->current_par.crtc.depth) {
+	case 8:
+		size = 256;
+		break;
+	case 16:
+		size = 64;
+		break;
+	default:
+		size = 32;
+		break;	/* possible problems in kernel code without this */
+	}
+#else
 	int size = (fb_display[con].var.bits_per_pixel <= 8) ? 256 : 32;
+#endif
+
 	fb_copy_cmap(fb_default_cmap(size), cmap, kspc ? 0 : 2);
     }
 #endif
@@ -1589,7 +1627,24 @@
 	disp = info->disp;

     if (!disp->cmap.len) {      /* no colormap allocated? */
-        int size = (disp->var.bits_per_pixel <= 8) ? 256 : 32;
+#if 1
+	int size;
+
+	switch (fb->current_par.crtc.depth) {
+	case 8:
+		size = 256;
+		break;
+	case 16:
+		size = 64;
+		break;
+	default:
+		size = 32;
+		break;	/* possible problems in kernel code without this */
+	}
+#else
+	int size = (disp->var.bits_per_pixel <= 8) ? 256 : 32;
+#endif
+
 	if ((err = fb_alloc_cmap(&disp->cmap, size, 0)))
 	    return err;
     }
@@ -2211,6 +2266,7 @@
 {
     struct fb_info_aty128 *info = (struct fb_info_aty128 *)fb;
     u32 col;
+    u_int palreg;

     if (regno > 255)
 	return 1;
@@ -2233,7 +2289,7 @@
         if (info->chip_gen == rage_M3)
             aty_st_le32(DAC_CNTL, aty_ld_le32(DAC_CNTL) & ~DAC_PALETTE_ACCESS_CNTL);

-        for (i=16; i<256; i++) {
+        for (i=0; i<256; i++) {
             aty_st_8(PALETTE_INDEX, i);
             col = (i << 16) | (i << 8) | i;
             aty_st_le32(PALETTE_DATA, col);
@@ -2242,7 +2298,7 @@
         if (info->chip_gen == rage_M3) {
             aty_st_le32(DAC_CNTL, aty_ld_le32(DAC_CNTL) | DAC_PALETTE_ACCESS_CNTL);

-            for (i=16; i<256; i++) {
+            for (i=0; i<256; i++) {
                 aty_st_8(PALETTE_INDEX, i);
                 col = (i << 16) | (i << 8) | i;
                 aty_st_le32(PALETTE_DATA, col);
@@ -2256,27 +2312,41 @@
         aty_st_le32(DAC_CNTL, aty_ld_le32(DAC_CNTL) & ~DAC_PALETTE_ACCESS_CNTL);

     if (info->current_par.crtc.bpp == 16)
-        aty_st_8(PALETTE_INDEX, (regno << 3));
+    {
+        palreg = regno << 3;
+        if (info->current_par.crtc.depth == 16 && regno >= 32)
+	{
+        	palreg -= 252;
+		col = (info->palette[regno >> 1].red << 16) | (green << 8) | info->palette[regno >> 1].blue;
+	}
+	else
+		col = (red << 16) | (green << 8) | blue;
+    }
     else
-        aty_st_8(PALETTE_INDEX, regno);
-    col = (red << 16) | (green << 8) | blue;
+    {
+	palreg = regno;
+	col = (red << 16) | (green << 8) | blue;
+    }
+
+    aty_st_8(PALETTE_INDEX, palreg);
     aty_st_le32(PALETTE_DATA, col);
     if (info->chip_gen == rage_M3) {
     	aty_st_le32(DAC_CNTL, aty_ld_le32(DAC_CNTL) | DAC_PALETTE_ACCESS_CNTL);
-        if (info->current_par.crtc.bpp == 16)
-            aty_st_8(PALETTE_INDEX, (regno << 3));
-        else
-            aty_st_8(PALETTE_INDEX, regno);
+        aty_st_8(PALETTE_INDEX, palreg);
         aty_st_le32(PALETTE_DATA, col);
     }

     if (regno < 16)
-	switch (info->current_par.crtc.bpp) {
+	switch (info->current_par.crtc.depth) {
 #ifdef FBCON_HAS_CFB16
-	case 9 ... 16:
+	case 9 ... 15:
 	    info->fbcon_cmap.cfb16[regno] = (regno << 10) | (regno << 5) |
                 regno;
 	    break;
+	case 16:
+	    info->fbcon_cmap.cfb16[regno] = (regno << 11) | (regno << 6) |
+                regno;
+	    break;
 #endif
 #ifdef FBCON_HAS_CFB24
 	case 17 ... 24:
@@ -2309,7 +2379,24 @@
     if (fb_display[con].cmap.len)
 	fb_set_cmap(&fb_display[con].cmap, 1, aty128_setcolreg, info);
     else {
-	int size = (fb_display[con].var.bits_per_pixel <= 8) ? 256 : 16;
+#if 1
+	int size;
+
+	switch (fb->current_par.crtc.depth) {
+	case 8:
+		size = 256;
+		break;
+	case 16:
+		size = 64;
+		break;
+	default:
+		size = 32;
+		break;	/* possible problems in kernel code without this */
+	}
+#else
+	int size = (fb_display[con].var.bits_per_pixel <= 8) ? 256 : 32;
+#endif
+
 	fb_set_cmap(fb_default_cmap(size), 1, aty128_setcolreg, info);
     }
 }
@@ -2356,18 +2443,18 @@
 		u_int width, u_int height,
 		struct fb_info_aty128 *info)
 {
-    u32 save_dp_datatype, save_dp_cntl, bppval;
+    u32 save_dp_datatype, save_dp_cntl, dstval;

     if (!width || !height)
         return;

-    bppval = bpp_to_depth(info->current_par.crtc.bpp);
-    if (bppval == DST_24BPP) {
+    dstval = depth_to_dst(info->current_par.crtc.depth);
+    if (dstval == DST_24BPP) {
         srcx *= 3;
         dstx *= 3;
         width *= 3;
-    } else if (bppval == -EINVAL) {
-        printk("aty128fb: invalid depth\n");
+    } else if (dstval == -EINVAL) {
+        printk("aty128fb: invalid depth or RGBA\n");
         return;
     }

@@ -2379,7 +2466,7 @@
     aty_st_le32(SRC_Y_X, (srcy << 16) | srcx);
     aty_st_le32(DP_MIX, ROP3_SRCCOPY | DP_SRC_RECT);
     aty_st_le32(DP_CNTL, DST_X_LEFT_TO_RIGHT | DST_Y_TOP_TO_BOTTOM);
-    aty_st_le32(DP_DATATYPE, save_dp_datatype | bppval | SRC_DSTCOLOR);
+    aty_st_le32(DP_DATATYPE, save_dp_datatype | dstval | SRC_DSTCOLOR);

     aty_st_le32(DST_Y_X, (dsty << 16) | dstx);
     aty_st_le32(DST_HEIGHT_WIDTH, (height << 16) | width);

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2001-02-02 15:00 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2001-01-31 20:29 [linux-fbdev] Re: r128 DRI driver now fully functional Petr Vandrovec
2001-02-02 15:00 ` Michel Dänzer

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).