All of lore.kernel.org
 help / color / mirror / Atom feed
* [patch 0/6] [patch 0/6] Atari frame buffer fixes
@ 2008-12-21 15:00 Geert Uytterhoeven
  2008-12-21 15:01 ` [patch 1/6] fbdev: atafb - Fix line length handling Geert Uytterhoeven
                   ` (6 more replies)
  0 siblings, 7 replies; 12+ messages in thread
From: Geert Uytterhoeven @ 2008-12-21 15:00 UTC (permalink / raw)
  To: Michael Schmitz, linux-fbdev-devel; +Cc: linux-m68k, linux-kernel

This patchsets contains several fixes for the Atari frame buffer device, and
includes a refactoring of the c2p (Chunky-to-Planar) code:
  [1] fbdev: atafb - Fix line length handling
  [2] fbdev: atafb - Fix 16 bpp console
  [3] fbdev: c2p - Cleanups
  [4] fbdev: c2p - Extract common c2p core to c2p_core.h
  [5] fbdev: c2p/atafb - Add support for Atari interleaved bitplanes
  [6] fbdev: c2p - Rename c2p to c2p_planar and correct indentation

If nobody objects, I'd like to push this to Linus via the m68k tree, as the
c2p code is used by m68k drivers (atafb and amifb) only.

Gr{oetje,eeting}s,

						Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
							    -- Linus Torvalds


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

* [patch 1/6] fbdev: atafb - Fix line length handling
  2008-12-21 15:00 [patch 0/6] [patch 0/6] Atari frame buffer fixes Geert Uytterhoeven
@ 2008-12-21 15:01 ` Geert Uytterhoeven
  2008-12-21 15:01 ` [patch 2/6] fbdev: atafb - Fix 16 bpp console Geert Uytterhoeven
                   ` (5 subsequent siblings)
  6 siblings, 0 replies; 12+ messages in thread
From: Geert Uytterhoeven @ 2008-12-21 15:01 UTC (permalink / raw)
  To: Michael Schmitz, linux-fbdev-devel; +Cc: linux-m68k, linux-kernel

[-- Attachment #1: atafb-linelen.diff --]
[-- Type: text/plain, Size: 2387 bytes --]

  - Make sure par->next_line is always set (this was done for Falcon only),
    as all the text console drawing operations need a valid par->next_line,
  - Make sure fix->line_length is always set, as some userspace applications
    need it because they don't have fallback code for the case where it's zero.

Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org>
---
 drivers/video/atafb.c |   12 ++++++++----
 1 file changed, 8 insertions(+), 4 deletions(-)

--- a/drivers/video/atafb.c
+++ b/drivers/video/atafb.c
@@ -614,7 +614,7 @@ static int tt_encode_fix(struct fb_fix_s
 	fix->xpanstep = 0;
 	fix->ypanstep = 1;
 	fix->ywrapstep = 0;
-	fix->line_length = 0;
+	fix->line_length = par->next_line;
 	fix->accel = FB_ACCEL_ATARIBLITT;
 	return 0;
 }
@@ -691,6 +691,7 @@ static int tt_decode_var(struct fb_var_s
 		return -EINVAL;
 	par->yres_virtual = yres_virtual;
 	par->screen_base = screen_base + var->yoffset * linelen;
+	par->next_line = linelen;
 	return 0;
 }
 
@@ -918,7 +919,7 @@ static int falcon_encode_fix(struct fb_f
 		fix->visual = FB_VISUAL_TRUECOLOR;
 		fix->xpanstep = 2;
 	}
-	fix->line_length = 0;
+	fix->line_length = par->next_line;
 	fix->accel = FB_ACCEL_ATARIBLITT;
 	return 0;
 }
@@ -1852,7 +1853,7 @@ static int stste_encode_fix(struct fb_fi
 		fix->ypanstep = 0;
 	}
 	fix->ywrapstep = 0;
-	fix->line_length = 0;
+	fix->line_length = par->next_line;
 	fix->accel = FB_ACCEL_ATARIBLITT;
 	return 0;
 }
@@ -1910,6 +1911,7 @@ static int stste_decode_var(struct fb_va
 		return -EINVAL;
 	par->yres_virtual = yres_virtual;
 	par->screen_base = screen_base + var->yoffset * linelen;
+	par->next_line = linelen;
 	return 0;
 }
 
@@ -2169,7 +2171,7 @@ static int ext_encode_fix(struct fb_fix_
 	fix->xpanstep = 0;
 	fix->ypanstep = 0;
 	fix->ywrapstep = 0;
-	fix->line_length = 0;
+	fix->line_length = par->next_line;
 	return 0;
 }
 
@@ -2184,6 +2186,8 @@ static int ext_decode_var(struct fb_var_
 	    var->xoffset > 0 ||
 	    var->yoffset > 0)
 		return -EINVAL;
+
+	par->next_line = external_xres_virtual * external_depth / 8;
 	return 0;
 }
 

-- 
Gr{oetje,eeting}s,

						Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
							    -- Linus Torvalds


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

* [patch 2/6] fbdev: atafb - Fix 16 bpp console
  2008-12-21 15:00 [patch 0/6] [patch 0/6] Atari frame buffer fixes Geert Uytterhoeven
  2008-12-21 15:01 ` [patch 1/6] fbdev: atafb - Fix line length handling Geert Uytterhoeven
@ 2008-12-21 15:01 ` Geert Uytterhoeven
  2008-12-21 15:01 ` [patch 3/6] fbdev: c2p - Cleanups Geert Uytterhoeven
                   ` (4 subsequent siblings)
  6 siblings, 0 replies; 12+ messages in thread
From: Geert Uytterhoeven @ 2008-12-21 15:01 UTC (permalink / raw)
  To: Michael Schmitz, linux-fbdev-devel; +Cc: linux-m68k, linux-kernel

[-- Attachment #1: atafb-16bpp.diff --]
[-- Type: text/plain, Size: 4259 bytes --]

  - 16 bpp must use the cfb_*() ops
  - 16 bpp needs to set up info->pseudo_palette[] (was fbcon_cfb16_cmap[] in
    2.4.x)
  - Kill commented out 2.4.x fbcon remnants

Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org>
---
 drivers/video/atafb.c |   74 ++++++++++++++++++++------------------------------
 1 file changed, 30 insertions(+), 44 deletions(-)

--- a/drivers/video/atafb.c
+++ b/drivers/video/atafb.c
@@ -149,6 +149,7 @@ static struct atafb_par {
 			short mono;
 			short ste_mode;
 			short bpp;
+			u32 pseudo_palette[16];
 		} falcon;
 #endif
 		/* Nothing needed for external mode */
@@ -885,10 +886,6 @@ static int vdl_prescale[4][3] = {
 /* Default hsync timing [mon_type] in picoseconds */
 static long h_syncs[4] = { 3000000, 4875000, 4000000, 4875000 };
 
-#ifdef FBCON_HAS_CFB16
-static u16 fbcon_cfb16_cmap[16];
-#endif
-
 static inline int hxx_prescale(struct falcon_hw *hw)
 {
 	return hw->ste_mode ? 16
@@ -1736,10 +1733,10 @@ static int falcon_setcolreg(unsigned int
 			(((red & 0xe000) >> 13) | ((red & 0x1000) >> 12) << 8) |
 			(((green & 0xe000) >> 13) | ((green & 0x1000) >> 12) << 4) |
 			((blue & 0xe000) >> 13) | ((blue & 0x1000) >> 12);
-#ifdef FBCON_HAS_CFB16
-		fbcon_cfb16_cmap[regno] = ((red & 0xf800) |
-					   ((green & 0xfc00) >> 5) |
-					   ((blue & 0xf800) >> 11));
+#ifdef ATAFB_FALCON
+		((u32 *)info->pseudo_palette)[regno] = ((red & 0xf800) |
+						       ((green & 0xfc00) >> 5) |
+						       ((blue & 0xf800) >> 11));
 #endif
 	}
 	return 0;
@@ -2447,42 +2444,6 @@ static void atafb_set_disp(struct fb_inf
 	atafb_get_fix(&info->fix, info);
 
 	info->screen_base = (void *)info->fix.smem_start;
-
-	switch (info->fix.type) {
-	case FB_TYPE_INTERLEAVED_PLANES:
-		switch (info->var.bits_per_pixel) {
-		case 2:
-			// display->dispsw = &fbcon_iplan2p2;
-			break;
-		case 4:
-			// display->dispsw = &fbcon_iplan2p4;
-			break;
-		case 8:
-			// display->dispsw = &fbcon_iplan2p8;
-			break;
-		}
-		break;
-	case FB_TYPE_PACKED_PIXELS:
-		switch (info->var.bits_per_pixel) {
-#ifdef FBCON_HAS_MFB
-		case 1:
-			// display->dispsw = &fbcon_mfb;
-			break;
-#endif
-#ifdef FBCON_HAS_CFB8
-		case 8:
-			// display->dispsw = &fbcon_cfb8;
-			break;
-#endif
-#ifdef FBCON_HAS_CFB16
-		case 16:
-			// display->dispsw = &fbcon_cfb16;
-			// display->dispsw_data = fbcon_cfb16_cmap;
-			break;
-#endif
-		}
-		break;
-	}
 }
 
 static int atafb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
@@ -2553,6 +2514,13 @@ static void atafb_fillrect(struct fb_inf
 	if (!rect->width || !rect->height)
 		return;
 
+#ifdef ATAFB_FALCON
+	if (info->var.bits_per_pixel == 16) {
+		cfb_fillrect(info, rect);
+		return;
+	}
+#endif
+
 	/*
 	 * We could use hardware clipping but on many cards you get around
 	 * hardware clipping by writing to framebuffer directly.
@@ -2587,6 +2555,13 @@ static void atafb_copyarea(struct fb_inf
 	u32 dx, dy, sx, sy, width, height;
 	int rev_copy = 0;
 
+#ifdef ATAFB_FALCON
+	if (info->var.bits_per_pixel == 16) {
+		cfb_copyarea(info, area);
+		return;
+	}
+#endif
+
 	/* clip the destination */
 	x2 = area->dx + area->width;
 	y2 = area->dy + area->height;
@@ -2636,6 +2611,13 @@ static void atafb_imageblit(struct fb_in
 	const char *src;
 	u32 dx, dy, width, height, pitch;
 
+#ifdef ATAFB_FALCON
+	if (info->var.bits_per_pixel == 16) {
+		cfb_imageblit(info, image);
+		return;
+	}
+#endif
+
 	/*
 	 * We could use hardware clipping but on many cards you get around
 	 * hardware clipping by writing to framebuffer directly like we are
@@ -3229,6 +3211,10 @@ int __init atafb_init(void)
 	// tries to read from HW which may not be initialized yet
 	// so set sane var first, then call atafb_set_par
 	atafb_get_var(&fb_info.var, &fb_info);
+
+#ifdef ATAFB_FALCON
+	fb_info.pseudo_palette = current_par.hw.falcon.pseudo_palette;
+#endif
 	fb_info.flags = FBINFO_FLAG_DEFAULT;
 
 	if (!fb_find_mode(&fb_info.var, &fb_info, mode_option, atafb_modedb,

-- 
Gr{oetje,eeting}s,

						Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
							    -- Linus Torvalds


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

* [patch 3/6] fbdev: c2p - Cleanups
  2008-12-21 15:00 [patch 0/6] [patch 0/6] Atari frame buffer fixes Geert Uytterhoeven
  2008-12-21 15:01 ` [patch 1/6] fbdev: atafb - Fix line length handling Geert Uytterhoeven
  2008-12-21 15:01 ` [patch 2/6] fbdev: atafb - Fix 16 bpp console Geert Uytterhoeven
@ 2008-12-21 15:01 ` Geert Uytterhoeven
  2008-12-22 23:22   ` Andrew Morton
  2008-12-21 15:01 ` [patch 4/6] fbdev: c2p - Extract common c2p core to c2p_core.h Geert Uytterhoeven
                   ` (3 subsequent siblings)
  6 siblings, 1 reply; 12+ messages in thread
From: Geert Uytterhoeven @ 2008-12-21 15:01 UTC (permalink / raw)
  To: Michael Schmitz, linux-fbdev-devel; +Cc: linux-m68k, linux-kernel

[-- Attachment #1: c2p-prepare.diff --]
[-- Type: text/plain, Size: 6382 bytes --]

  - Improve comments and naming
  - Use void * for arbitrary pointers
  - Use a union to represent pixels/words, to avoid casts

Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org>
---
 drivers/video/c2p.c |   80 +++++++++++++++++++++++++++-------------------------
 drivers/video/c2p.h |    6 +--
 2 files changed, 45 insertions(+), 41 deletions(-)

--- a/drivers/video/c2p.c
+++ b/drivers/video/c2p.c
@@ -54,7 +54,7 @@ static inline u32 get_mask(int n)
     return 0;
 }
 
-#define transp_nx1(d, n)				\
+#define transp8_nx1(d, n)				\
     do {						\
 	u32 mask = get_mask(n);				\
 	/* First block */				\
@@ -67,7 +67,7 @@ static inline u32 get_mask(int n)
 	_transp(d, 6, 7, n, mask);			\
     } while (0)
 
-#define transp_nx2(d, n)				\
+#define transp8_nx2(d, n)				\
     do {						\
 	u32 mask = get_mask(n);				\
 	/* First block */				\
@@ -78,40 +78,41 @@ static inline u32 get_mask(int n)
 	_transp(d, 5, 7, n, mask);			\
     } while (0)
 
-#define transp_nx4(d, n)				\
+#define transp8_nx4(d, n)				\
     do {						\
 	u32 mask = get_mask(n);				\
+	/* Single block */				\
 	_transp(d, 0, 4, n, mask);			\
 	_transp(d, 1, 5, n, mask);			\
 	_transp(d, 2, 6, n, mask);			\
 	_transp(d, 3, 7, n, mask);			\
     } while (0)
 
-#define transp(d, n, m)	transp_nx ## m(d, n)
+#define transp8(d, n, m)	transp8_nx ## m(d, n)
 
 
     /*
      *  Perform a full C2P step on 32 8-bit pixels, stored in 8 32-bit words
      *  containing
      *    - 32 8-bit chunky pixels on input
-     *    - permuted planar data on output
+     *    - permutated planar data (1 plane per 32-bit word) on output
      */
 
-static void c2p_8bpp(u32 d[8])
+static void c2p_32x8(u32 d[8])
 {
-    transp(d, 16, 4);
-    transp(d, 8, 2);
-    transp(d, 4, 1);
-    transp(d, 2, 4);
-    transp(d, 1, 2);
+    transp8(d, 16, 4);
+    transp8(d, 8, 2);
+    transp8(d, 4, 1);
+    transp8(d, 2, 4);
+    transp8(d, 1, 2);
 }
 
 
     /*
-     *  Array containing the permution indices of the planar data after c2p
+     *  Array containing the permutation indices of the planar data after c2p
      */
 
-static const int perm_c2p_8bpp[8] = { 7, 5, 3, 1, 6, 4, 2, 0 };
+static const int perm_c2p_32x8[8] = { 7, 5, 3, 1, 6, 4, 2, 0 };
 
 
     /*
@@ -130,12 +131,12 @@ static inline unsigned long comp(unsigne
      *  Store a full block of planar data after c2p conversion
      */
 
-static inline void store_planar(char *dst, u32 dst_inc, u32 bpp, u32 d[8])
+static inline void store_planar(void *dst, u32 dst_inc, u32 bpp, u32 d[8])
 {
     int i;
 
     for (i = 0; i < bpp; i++, dst += dst_inc)
-	*(u32 *)dst = d[perm_c2p_8bpp[i]];
+	*(u32 *)dst = d[perm_c2p_32x8[i]];
 }
 
 
@@ -143,13 +144,13 @@ static inline void store_planar(char *ds
      *  Store a partial block of planar data after c2p conversion
      */
 
-static inline void store_planar_masked(char *dst, u32 dst_inc, u32 bpp,
+static inline void store_planar_masked(void *dst, u32 dst_inc, u32 bpp,
 				       u32 d[8], u32 mask)
 {
     int i;
 
     for (i = 0; i < bpp; i++, dst += dst_inc)
-	*(u32 *)dst = comp(d[perm_c2p_8bpp[i]], *(u32 *)dst, mask);
+	*(u32 *)dst = comp(d[perm_c2p_32x8[i]], *(u32 *)dst, mask);
 }
 
 
@@ -166,18 +167,21 @@ static inline void store_planar_masked(c
      *  @bpp: Bits per pixel of the planar frame buffer (1-8)
      */
 
-void c2p(u8 *dst, const u8 *src, u32 dx, u32 dy, u32 width, u32 height,
+void c2p(void *dst, const void *src, u32 dx, u32 dy, u32 width, u32 height,
 	 u32 dst_nextline, u32 dst_nextplane, u32 src_nextline, u32 bpp)
 {
-    int dst_idx;
-    u32 d[8], first, last, w;
+    union {
+	u8 pixels[32];
+	u32 words[8];
+    } d;
+    u32 dst_idx, first, last, w;
     const u8 *c;
-    u8 *p;
+    void *p;
 
     dst += dy*dst_nextline+(dx & ~31);
     dst_idx = dx % 32;
-    first = ~0UL >> dst_idx;
-    last = ~(~0UL >> ((dst_idx+width) % 32));
+    first = 0xffffffffU >> dst_idx;
+    last = ~(0xffffffffU >> ((dst_idx+width) % 32));
     while (height--) {
 	c = src;
 	p = dst;
@@ -185,11 +189,11 @@ void c2p(u8 *dst, const u8 *src, u32 dx,
 	if (dst_idx+width <= 32) {
 	    /* Single destination word */
 	    first &= last;
-	    memset(d, 0, sizeof(d));
-	    memcpy((u8 *)d+dst_idx, c, width);
+	    memset(d.pixels, 0, sizeof(d));
+	    memcpy(d.pixels+dst_idx, c, width);
 	    c += width;
-	    c2p_8bpp(d);
-	    store_planar_masked(p, dst_nextplane, bpp, d, first);
+	    c2p_32x8(d.words);
+	    store_planar_masked(p, dst_nextplane, bpp, d.words, first);
 	    p += 4;
 	} else {
 	    /* Multiple destination words */
@@ -197,30 +201,30 @@ void c2p(u8 *dst, const u8 *src, u32 dx,
 	    /* Leading bits */
 	    if (dst_idx) {
 		w = 32 - dst_idx;
-		memset(d, 0, dst_idx);
-		memcpy((u8 *)d+dst_idx, c, w);
+		memset(d.pixels, 0, dst_idx);
+		memcpy(d.pixels+dst_idx, c, w);
 		c += w;
-		c2p_8bpp(d);
-		store_planar_masked(p, dst_nextplane, bpp, d, first);
+		c2p_32x8(d.words);
+		store_planar_masked(p, dst_nextplane, bpp, d.words, first);
 		p += 4;
 		w = width-w;
 	    }
 	    /* Main chunk */
 	    while (w >= 32) {
-		memcpy(d, c, 32);
+		memcpy(d.pixels, c, 32);
 		c += 32;
-		c2p_8bpp(d);
-		store_planar(p, dst_nextplane, bpp, d);
+		c2p_32x8(d.words);
+		store_planar(p, dst_nextplane, bpp, d.words);
 		p += 4;
 		w -= 32;
 	    }
 	    /* Trailing bits */
 	    w %= 32;
 	    if (w > 0) {
-		memcpy(d, c, w);
-		memset((u8 *)d+w, 0, 32-w);
-		c2p_8bpp(d);
-		store_planar_masked(p, dst_nextplane, bpp, d, last);
+		memcpy(d.pixels, c, w);
+		memset(d.pixels+w, 0, 32-w);
+		c2p_32x8(d.words);
+		store_planar_masked(p, dst_nextplane, bpp, d.words, last);
 	    }
 	}
 	src += src_nextline;
--- a/drivers/video/c2p.h
+++ b/drivers/video/c2p.h
@@ -10,7 +10,7 @@
 
 #include <linux/types.h>
 
-extern void c2p(u8 *dst, const u8 *src, u32 dx, u32 dy, u32 width, u32 height,
-		u32 dst_nextline, u32 dst_nextplane, u32 src_nextline,
-		u32 bpp);
+extern void c2p(void *dst, const void *src, u32 dx, u32 dy, u32 width,
+	        u32 height, u32 dst_nextline, u32 dst_nextplane,
+		u32 src_nextline, u32 bpp);
 

-- 
Gr{oetje,eeting}s,

						Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
							    -- Linus Torvalds


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

* [patch 4/6] fbdev: c2p - Extract common c2p core to c2p_core.h
  2008-12-21 15:00 [patch 0/6] [patch 0/6] Atari frame buffer fixes Geert Uytterhoeven
                   ` (2 preceding siblings ...)
  2008-12-21 15:01 ` [patch 3/6] fbdev: c2p - Cleanups Geert Uytterhoeven
@ 2008-12-21 15:01 ` Geert Uytterhoeven
  2008-12-21 15:01 ` [patch 5/6] fbdev: c2p/atafb - Add support for Atari interleaved bitplanes Geert Uytterhoeven
                   ` (2 subsequent siblings)
  6 siblings, 0 replies; 12+ messages in thread
From: Geert Uytterhoeven @ 2008-12-21 15:01 UTC (permalink / raw)
  To: Michael Schmitz, linux-fbdev-devel; +Cc: linux-m68k, linux-kernel

[-- Attachment #1: c2p-extract-common.diff --]
[-- Type: text/plain, Size: 4802 bytes --]

Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org>
---
 drivers/video/c2p.c      |   87 ----------------------------------------
 drivers/video/c2p_core.h |  101 +++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 102 insertions(+), 86 deletions(-)

--- a/drivers/video/c2p.c
+++ b/drivers/video/c2p.c
@@ -15,80 +15,7 @@
 #include <linux/module.h>
 #include <linux/string.h>
 #include "c2p.h"
-
-
-    /*
-     *  Basic transpose step
-     */
-
-#define _transp(d, i1, i2, shift, mask)			\
-    do {						\
-	u32 t = (d[i1] ^ (d[i2] >> shift)) & mask;	\
-	d[i1] ^= t;					\
-	d[i2] ^= t << shift;				\
-    } while (0)
-
-static inline u32 get_mask(int n)
-{
-    switch (n) {
-	case 1:
-	    return 0x55555555;
-	    break;
-
-	case 2:
-	    return 0x33333333;
-	    break;
-
-	case 4:
-	    return 0x0f0f0f0f;
-	    break;
-
-	case 8:
-	    return 0x00ff00ff;
-	    break;
-
-	case 16:
-	    return 0x0000ffff;
-	    break;
-    }
-    return 0;
-}
-
-#define transp8_nx1(d, n)				\
-    do {						\
-	u32 mask = get_mask(n);				\
-	/* First block */				\
-	_transp(d, 0, 1, n, mask);			\
-	/* Second block */				\
-	_transp(d, 2, 3, n, mask);			\
-	/* Third block */				\
-	_transp(d, 4, 5, n, mask);			\
-	/* Fourth block */				\
-	_transp(d, 6, 7, n, mask);			\
-    } while (0)
-
-#define transp8_nx2(d, n)				\
-    do {						\
-	u32 mask = get_mask(n);				\
-	/* First block */				\
-	_transp(d, 0, 2, n, mask);			\
-	_transp(d, 1, 3, n, mask);			\
-	/* Second block */				\
-	_transp(d, 4, 6, n, mask);			\
-	_transp(d, 5, 7, n, mask);			\
-    } while (0)
-
-#define transp8_nx4(d, n)				\
-    do {						\
-	u32 mask = get_mask(n);				\
-	/* Single block */				\
-	_transp(d, 0, 4, n, mask);			\
-	_transp(d, 1, 5, n, mask);			\
-	_transp(d, 2, 6, n, mask);			\
-	_transp(d, 3, 7, n, mask);			\
-    } while (0)
-
-#define transp8(d, n, m)	transp8_nx ## m(d, n)
+#include "c2p_core.h"
 
 
     /*
@@ -116,18 +43,6 @@ static const int perm_c2p_32x8[8] = { 7,
 
 
     /*
-     *  Compose two values, using a bitmask as decision value
-     *  This is equivalent to (a & mask) | (b & ~mask)
-     */
-
-static inline unsigned long comp(unsigned long a, unsigned long b,
-				 unsigned long mask)
-{
-	return ((a ^ b) & mask) ^ b;
-}
-
-
-    /*
      *  Store a full block of planar data after c2p conversion
      */
 
--- /dev/null
+++ b/drivers/video/c2p_core.h
@@ -0,0 +1,101 @@
+/*
+ *  Fast C2P (Chunky-to-Planar) Conversion
+ *
+ *  Copyright (C) 2003-2008 Geert Uytterhoeven
+ *
+ *  This file is subject to the terms and conditions of the GNU General Public
+ *  License. See the file COPYING in the main directory of this archive
+ *  for more details.
+ */
+
+
+    /*
+     *  Basic transpose step
+     */
+
+#define _transp(d, i1, i2, shift, mask)				\
+	do {							\
+		u32 t = (d[i1] ^ (d[i2] >> shift)) & mask;	\
+		d[i1] ^= t;					\
+		d[i2] ^= t << shift;				\
+	} while (0)
+
+
+static inline u32 get_mask(int n)
+{
+	switch (n) {
+	case 1:
+		return 0x55555555;
+		break;
+
+	case 2:
+		return 0x33333333;
+		break;
+
+	case 4:
+		return 0x0f0f0f0f;
+		break;
+
+	case 8:
+		return 0x00ff00ff;
+		break;
+
+	case 16:
+		return 0x0000ffff;
+		break;
+	}
+	return 0;
+}
+
+
+    /*
+     *  Transpose operations on 8 32-bit words
+     */
+
+#define transp8_nx1(d, n)					\
+	do {							\
+		u32 mask = get_mask(n);				\
+		/* First block */				\
+		_transp(d, 0, 1, n, mask);			\
+		/* Second block */				\
+		_transp(d, 2, 3, n, mask);			\
+		/* Third block */				\
+		_transp(d, 4, 5, n, mask);			\
+		/* Fourth block */				\
+		_transp(d, 6, 7, n, mask);			\
+	} while (0)
+
+#define transp8_nx2(d, n)					\
+	do {							\
+		u32 mask = get_mask(n);				\
+		/* First block */				\
+		_transp(d, 0, 2, n, mask);			\
+		_transp(d, 1, 3, n, mask);			\
+		/* Second block */				\
+		_transp(d, 4, 6, n, mask);			\
+		_transp(d, 5, 7, n, mask);			\
+	} while (0)
+
+#define transp8_nx4(d, n)					\
+	do {							\
+		u32 mask = get_mask(n);				\
+		/* Single block */				\
+		_transp(d, 0, 4, n, mask);			\
+		_transp(d, 1, 5, n, mask);			\
+		_transp(d, 2, 6, n, mask);			\
+		_transp(d, 3, 7, n, mask);			\
+	} while (0)
+
+#define transp8(d, n, m)	transp8_nx ## m(d, n)
+
+
+    /*
+     *  Compose two values, using a bitmask as decision value
+     *  This is equivalent to (a & mask) | (b & ~mask)
+     */
+
+static inline unsigned long comp(unsigned long a, unsigned long b,
+				 unsigned long mask)
+{
+	return ((a ^ b) & mask) ^ b;
+}

-- 
Gr{oetje,eeting}s,

						Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
							    -- Linus Torvalds


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

* [patch 5/6] fbdev: c2p/atafb - Add support for Atari interleaved bitplanes
  2008-12-21 15:00 [patch 0/6] [patch 0/6] Atari frame buffer fixes Geert Uytterhoeven
                   ` (3 preceding siblings ...)
  2008-12-21 15:01 ` [patch 4/6] fbdev: c2p - Extract common c2p core to c2p_core.h Geert Uytterhoeven
@ 2008-12-21 15:01 ` Geert Uytterhoeven
  2008-12-21 15:01 ` [patch 6/6] fbdev: c2p - Rename c2p to c2p_planar and correct indentation Geert Uytterhoeven
  2008-12-22 23:24 ` [patch 0/6] [patch 0/6] Atari frame buffer fixes Andrew Morton
  6 siblings, 0 replies; 12+ messages in thread
From: Geert Uytterhoeven @ 2008-12-21 15:01 UTC (permalink / raw)
  To: Michael Schmitz, linux-fbdev-devel; +Cc: linux-m68k, linux-kernel

[-- Attachment #1: c2p-iplan2p.diff --]
[-- Type: text/plain, Size: 8114 bytes --]

The c2p() for normal bitplanes is not suitable for interleaved bitplanes with
2 bytes of interleave, causing a garbled penguin logo. Add c2p_iplan2().

Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org>
---
 drivers/video/Makefile     |    2 
 drivers/video/atafb.c      |   15 ----
 drivers/video/c2p.h        |    5 +
 drivers/video/c2p_core.h   |   39 +++++++++++
 drivers/video/c2p_iplan2.c |  153 +++++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 200 insertions(+), 14 deletions(-)

--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -72,7 +72,7 @@ obj-$(CONFIG_FB_TCX)              += tcx
 obj-$(CONFIG_FB_LEO)              += leo.o sbuslib.o
 obj-$(CONFIG_FB_SGIVW)            += sgivwfb.o
 obj-$(CONFIG_FB_ACORN)            += acornfb.o
-obj-$(CONFIG_FB_ATARI)            += atafb.o c2p.o atafb_mfb.o \
+obj-$(CONFIG_FB_ATARI)            += atafb.o c2p_iplan2.o atafb_mfb.o \
                                      atafb_iplan2p2.o atafb_iplan2p4.o atafb_iplan2p8.o
 obj-$(CONFIG_FB_MAC)              += macfb.o
 obj-$(CONFIG_FB_HECUBA)           += hecubafb.o
--- a/drivers/video/atafb.c
+++ b/drivers/video/atafb.c
@@ -122,7 +122,6 @@ static struct atafb_par {
 	void *screen_base;
 	int yres_virtual;
 	u_long next_line;
-	u_long next_plane;
 #if defined ATAFB_TT || defined ATAFB_STE
 	union {
 		struct {
@@ -1392,14 +1391,7 @@ set_screen_base:
 	par->screen_base = screen_base + var->yoffset * linelen;
 	par->hw.falcon.xoffset = 0;
 
-	// FIXME!!! sort of works, no crash
-	//par->next_line = linelen;
-	//par->next_plane = yres_virtual * linelen;
 	par->next_line = linelen;
-	par->next_plane = 2;
-	// crashes
-	//par->next_plane = linelen;
-	//par->next_line  = yres_virtual * linelen;
 
 	return 0;
 }
@@ -2662,10 +2654,9 @@ static void atafb_imageblit(struct fb_in
 			src += pitch;
 		}
 	} else {
-		// only used for logo; broken
-		c2p(info->screen_base, image->data, dx, dy, width, height,
-		    par->next_line, par->next_plane, image->width,
-		    info->var.bits_per_pixel);
+		c2p_iplan2(info->screen_base, image->data, dx, dy, width,
+			   height, par->next_line, image->width,
+			   info->var.bits_per_pixel);
 	}
 }
 
--- a/drivers/video/c2p.h
+++ b/drivers/video/c2p.h
@@ -1,7 +1,7 @@
 /*
  *  Fast C2P (Chunky-to-Planar) Conversion
  *
- *  Copyright (C) 2003 Geert Uytterhoeven
+ *  Copyright (C) 2003-2008 Geert Uytterhoeven
  *
  *  This file is subject to the terms and conditions of the GNU General Public
  *  License. See the file COPYING in the main directory of this archive
@@ -14,3 +14,6 @@ extern void c2p(void *dst, const void *s
 	        u32 height, u32 dst_nextline, u32 dst_nextplane,
 		u32 src_nextline, u32 bpp);
 
+extern void c2p_iplan2(void *dst, const void *src, u32 dx, u32 dy, u32 width,
+		       u32 height, u32 dst_nextline, u32 src_nextline,
+		       u32 bpp);
--- a/drivers/video/c2p_core.h
+++ b/drivers/video/c2p_core.h
@@ -90,6 +90,45 @@ static inline u32 get_mask(int n)
 
 
     /*
+     *  Transpose operations on 4 32-bit words
+     */
+
+#define transp4_nx1(d, n)					\
+	do {							\
+		u32 mask = get_mask(n);				\
+		/* First block */				\
+		_transp(d, 0, 1, n, mask);			\
+		/* Second block */				\
+		_transp(d, 2, 3, n, mask);			\
+	} while (0)
+
+#define transp4_nx2(d, n)					\
+	do {							\
+		u32 mask = get_mask(n);				\
+		/* Single block */				\
+		_transp(d, 0, 2, n, mask);			\
+		_transp(d, 1, 3, n, mask);			\
+	} while (0)
+
+#define transp4(d, n, m)	transp4_nx ## m(d, n)
+
+
+    /*
+     *  Transpose operations on 4 32-bit words (reverse order)
+     */
+
+#define transp4x_nx2(d, n)					\
+	do {							\
+		u32 mask = get_mask(n);				\
+		/* Single block */				\
+		_transp(d, 2, 0, n, mask);			\
+		_transp(d, 3, 1, n, mask);			\
+	} while (0)
+
+#define transp4x(d, n, m)	transp4x_nx ## m(d, n)
+
+
+    /*
      *  Compose two values, using a bitmask as decision value
      *  This is equivalent to (a & mask) | (b & ~mask)
      */
--- /dev/null
+++ b/drivers/video/c2p_iplan2.c
@@ -0,0 +1,153 @@
+/*
+ *  Fast C2P (Chunky-to-Planar) Conversion
+ *
+ *  Copyright (C) 2003-2008 Geert Uytterhoeven
+ *
+ *  NOTES:
+ *    - This code was inspired by Scout's C2P tutorial
+ *    - It assumes to run on a big endian system
+ *
+ *  This file is subject to the terms and conditions of the GNU General Public
+ *  License. See the file COPYING in the main directory of this archive
+ *  for more details.
+ */
+
+#include <linux/module.h>
+#include <linux/string.h>
+
+#include "c2p.h"
+#include "c2p_core.h"
+
+
+    /*
+     *  Perform a full C2P step on 16 8-bit pixels, stored in 4 32-bit words
+     *  containing
+     *    - 16 8-bit chunky pixels on input
+     *    - permutated planar data (2 planes per 32-bit word) on output
+     */
+
+static void c2p_16x8(u32 d[4])
+{
+	transp4(d, 8, 2);
+	transp4(d, 1, 2);
+	transp4x(d, 16, 2);
+	transp4x(d, 2, 2);
+	transp4(d, 4, 1);
+}
+
+
+    /*
+     *  Array containing the permutation indices of the planar data after c2p
+     */
+
+static const int perm_c2p_16x8[4] = { 1, 3, 0, 2 };
+
+
+    /*
+     *  Store a full block of iplan2 data after c2p conversion
+     */
+
+static inline void store_iplan2(void *dst, u32 bpp, u32 d[4])
+{
+	int i;
+
+	for (i = 0; i < bpp/2; i++, dst += 4)
+		*(u32 *)dst = d[perm_c2p_16x8[i]];
+}
+
+
+    /*
+     *  Store a partial block of iplan2 data after c2p conversion
+     */
+
+static inline void store_iplan2_masked(void *dst, u32 bpp, u32 d[4], u32 mask)
+{
+	int i;
+
+	for (i = 0; i < bpp/2; i++, dst += 4)
+		*(u32 *)dst = comp(d[perm_c2p_16x8[i]], *(u32 *)dst, mask);
+}
+
+
+    /*
+     *  c2p_iplan2 - Copy 8-bit chunky image data to an interleaved planar
+     *  frame buffer with 2 bytes of interleave
+     *  @dst: Starting address of the planar frame buffer
+     *  @dx: Horizontal destination offset (in pixels)
+     *  @dy: Vertical destination offset (in pixels)
+     *  @width: Image width (in pixels)
+     *  @height: Image height (in pixels)
+     *  @dst_nextline: Frame buffer offset to the next line (in bytes)
+     *  @src_nextline: Image offset to the next line (in bytes)
+     *  @bpp: Bits per pixel of the planar frame buffer (2, 4, or 8)
+     */
+
+void c2p_iplan2(void *dst, const void *src, u32 dx, u32 dy, u32 width,
+		u32 height, u32 dst_nextline, u32 src_nextline, u32 bpp)
+{
+	union {
+		u8 pixels[16];
+		u32 words[4];
+	} d;
+	u32 dst_idx, first, last, w;
+	const u8 *c;
+	void *p;
+
+	dst += dy*dst_nextline+(dx & ~15)*bpp;
+	dst_idx = dx % 16;
+	first = 0xffffU >> dst_idx;
+	first |= first << 16;
+	last = 0xffffU ^ (0xffffU >> ((dst_idx+width) % 16));
+	last |= last << 16;
+	while (height--) {
+		c = src;
+		p = dst;
+		w = width;
+		if (dst_idx+width <= 16) {
+			/* Single destination word */
+			first &= last;
+			memset(d.pixels, 0, sizeof(d));
+			memcpy(d.pixels+dst_idx, c, width);
+			c += width;
+			c2p_16x8(d.words);
+			store_iplan2_masked(p, bpp, d.words, first);
+			p += bpp*2;
+		} else {
+			/* Multiple destination words */
+			w = width;
+			/* Leading bits */
+			if (dst_idx) {
+				w = 16 - dst_idx;
+				memset(d.pixels, 0, dst_idx);
+				memcpy(d.pixels+dst_idx, c, w);
+				c += w;
+				c2p_16x8(d.words);
+				store_iplan2_masked(p, bpp, d.words, first);
+				p += bpp*2;
+				w = width-w;
+			}
+			/* Main chunk */
+			while (w >= 16) {
+				memcpy(d.pixels, c, 16);
+				c += 16;
+				c2p_16x8(d.words);
+				store_iplan2(p, bpp, d.words);
+				p += bpp*2;
+				w -= 16;
+			}
+			/* Trailing bits */
+			w %= 16;
+			if (w > 0) {
+				memcpy(d.pixels, c, w);
+				memset(d.pixels+w, 0, 16-w);
+				c2p_16x8(d.words);
+				store_iplan2_masked(p, bpp, d.words, last);
+			}
+		}
+		src += src_nextline;
+		dst += dst_nextline;
+	}
+}
+EXPORT_SYMBOL_GPL(c2p_iplan2);
+
+MODULE_LICENSE("GPL");

-- 
Gr{oetje,eeting}s,

						Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
							    -- Linus Torvalds


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

* [patch 6/6] fbdev: c2p - Rename c2p to c2p_planar and correct indentation
  2008-12-21 15:00 [patch 0/6] [patch 0/6] Atari frame buffer fixes Geert Uytterhoeven
                   ` (4 preceding siblings ...)
  2008-12-21 15:01 ` [patch 5/6] fbdev: c2p/atafb - Add support for Atari interleaved bitplanes Geert Uytterhoeven
@ 2008-12-21 15:01 ` Geert Uytterhoeven
  2008-12-22 23:23   ` Andrew Morton
  2008-12-22 23:24 ` [patch 0/6] [patch 0/6] Atari frame buffer fixes Andrew Morton
  6 siblings, 1 reply; 12+ messages in thread
From: Geert Uytterhoeven @ 2008-12-21 15:01 UTC (permalink / raw)
  To: Michael Schmitz, linux-fbdev-devel; +Cc: linux-m68k, linux-kernel

[-- Attachment #1: c2p-planar.diff --]
[-- Type: text/plain, Size: 10110 bytes --]

Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org>
---
 drivers/video/Makefile     |    2 
 drivers/video/amifb.c      |    6 -
 drivers/video/c2p.c        |  151 -------------------------------------------
 drivers/video/c2p.h        |    6 -
 drivers/video/c2p_planar.c |  156 +++++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 163 insertions(+), 158 deletions(-)

--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -28,7 +28,7 @@ obj-$(CONFIG_FB_DDC)           += fb_ddc
 obj-$(CONFIG_FB_DEFERRED_IO)   += fb_defio.o
 
 # Hardware specific drivers go first
-obj-$(CONFIG_FB_AMIGA)            += amifb.o c2p.o
+obj-$(CONFIG_FB_AMIGA)            += amifb.o c2p_planar.o
 obj-$(CONFIG_FB_ARC)              += arcfb.o
 obj-$(CONFIG_FB_CLPS711X)         += clps711xfb.o
 obj-$(CONFIG_FB_CYBER2000)        += cyber2000fb.o
--- a/drivers/video/amifb.c
+++ b/drivers/video/amifb.c
@@ -2159,9 +2159,9 @@ static void amifb_imageblit(struct fb_in
 			src += pitch;
 		}
 	} else {
-		c2p(info->screen_base, image->data, dx, dy, width, height,
-		    par->next_line, par->next_plane, image->width,
-		    info->var.bits_per_pixel);
+		c2p_planar(info->screen_base, image->data, dx, dy, width,
+			   height, par->next_line, par->next_plane,
+			   image->width, info->var.bits_per_pixel);
 	}
 }
 
--- a/drivers/video/c2p.c
+++ /dev/null
@@ -1,151 +0,0 @@
-/*
- *  Fast C2P (Chunky-to-Planar) Conversion
- *
- *  Copyright (C) 2003 Geert Uytterhoeven
- *
- *  NOTES:
- *    - This code was inspired by Scout's C2P tutorial
- *    - It assumes to run on a big endian system
- *
- *  This file is subject to the terms and conditions of the GNU General Public
- *  License. See the file COPYING in the main directory of this archive
- *  for more details.
- */
-
-#include <linux/module.h>
-#include <linux/string.h>
-#include "c2p.h"
-#include "c2p_core.h"
-
-
-    /*
-     *  Perform a full C2P step on 32 8-bit pixels, stored in 8 32-bit words
-     *  containing
-     *    - 32 8-bit chunky pixels on input
-     *    - permutated planar data (1 plane per 32-bit word) on output
-     */
-
-static void c2p_32x8(u32 d[8])
-{
-    transp8(d, 16, 4);
-    transp8(d, 8, 2);
-    transp8(d, 4, 1);
-    transp8(d, 2, 4);
-    transp8(d, 1, 2);
-}
-
-
-    /*
-     *  Array containing the permutation indices of the planar data after c2p
-     */
-
-static const int perm_c2p_32x8[8] = { 7, 5, 3, 1, 6, 4, 2, 0 };
-
-
-    /*
-     *  Store a full block of planar data after c2p conversion
-     */
-
-static inline void store_planar(void *dst, u32 dst_inc, u32 bpp, u32 d[8])
-{
-    int i;
-
-    for (i = 0; i < bpp; i++, dst += dst_inc)
-	*(u32 *)dst = d[perm_c2p_32x8[i]];
-}
-
-
-    /*
-     *  Store a partial block of planar data after c2p conversion
-     */
-
-static inline void store_planar_masked(void *dst, u32 dst_inc, u32 bpp,
-				       u32 d[8], u32 mask)
-{
-    int i;
-
-    for (i = 0; i < bpp; i++, dst += dst_inc)
-	*(u32 *)dst = comp(d[perm_c2p_32x8[i]], *(u32 *)dst, mask);
-}
-
-
-    /*
-     *  c2p - Copy 8-bit chunky image data to a planar frame buffer
-     *  @dst: Starting address of the planar frame buffer
-     *  @dx: Horizontal destination offset (in pixels)
-     *  @dy: Vertical destination offset (in pixels)
-     *  @width: Image width (in pixels)
-     *  @height: Image height (in pixels)
-     *  @dst_nextline: Frame buffer offset to the next line (in bytes)
-     *  @dst_nextplane: Frame buffer offset to the next plane (in bytes)
-     *  @src_nextline: Image offset to the next line (in bytes)
-     *  @bpp: Bits per pixel of the planar frame buffer (1-8)
-     */
-
-void c2p(void *dst, const void *src, u32 dx, u32 dy, u32 width, u32 height,
-	 u32 dst_nextline, u32 dst_nextplane, u32 src_nextline, u32 bpp)
-{
-    union {
-	u8 pixels[32];
-	u32 words[8];
-    } d;
-    u32 dst_idx, first, last, w;
-    const u8 *c;
-    void *p;
-
-    dst += dy*dst_nextline+(dx & ~31);
-    dst_idx = dx % 32;
-    first = 0xffffffffU >> dst_idx;
-    last = ~(0xffffffffU >> ((dst_idx+width) % 32));
-    while (height--) {
-	c = src;
-	p = dst;
-	w = width;
-	if (dst_idx+width <= 32) {
-	    /* Single destination word */
-	    first &= last;
-	    memset(d.pixels, 0, sizeof(d));
-	    memcpy(d.pixels+dst_idx, c, width);
-	    c += width;
-	    c2p_32x8(d.words);
-	    store_planar_masked(p, dst_nextplane, bpp, d.words, first);
-	    p += 4;
-	} else {
-	    /* Multiple destination words */
-	    w = width;
-	    /* Leading bits */
-	    if (dst_idx) {
-		w = 32 - dst_idx;
-		memset(d.pixels, 0, dst_idx);
-		memcpy(d.pixels+dst_idx, c, w);
-		c += w;
-		c2p_32x8(d.words);
-		store_planar_masked(p, dst_nextplane, bpp, d.words, first);
-		p += 4;
-		w = width-w;
-	    }
-	    /* Main chunk */
-	    while (w >= 32) {
-		memcpy(d.pixels, c, 32);
-		c += 32;
-		c2p_32x8(d.words);
-		store_planar(p, dst_nextplane, bpp, d.words);
-		p += 4;
-		w -= 32;
-	    }
-	    /* Trailing bits */
-	    w %= 32;
-	    if (w > 0) {
-		memcpy(d.pixels, c, w);
-		memset(d.pixels+w, 0, 32-w);
-		c2p_32x8(d.words);
-		store_planar_masked(p, dst_nextplane, bpp, d.words, last);
-	    }
-	}
-	src += src_nextline;
-	dst += dst_nextline;
-    }
-}
-EXPORT_SYMBOL_GPL(c2p);
-
-MODULE_LICENSE("GPL");
--- a/drivers/video/c2p.h
+++ b/drivers/video/c2p.h
@@ -10,9 +10,9 @@
 
 #include <linux/types.h>
 
-extern void c2p(void *dst, const void *src, u32 dx, u32 dy, u32 width,
-	        u32 height, u32 dst_nextline, u32 dst_nextplane,
-		u32 src_nextline, u32 bpp);
+extern void c2p_planar(void *dst, const void *src, u32 dx, u32 dy, u32 width,
+		       u32 height, u32 dst_nextline, u32 dst_nextplane,
+		       u32 src_nextline, u32 bpp);
 
 extern void c2p_iplan2(void *dst, const void *src, u32 dx, u32 dy, u32 width,
 		       u32 height, u32 dst_nextline, u32 src_nextline,
--- /dev/null
+++ b/drivers/video/c2p_planar.c
@@ -0,0 +1,156 @@
+/*
+ *  Fast C2P (Chunky-to-Planar) Conversion
+ *
+ *  Copyright (C) 2003-2008 Geert Uytterhoeven
+ *
+ *  NOTES:
+ *    - This code was inspired by Scout's C2P tutorial
+ *    - It assumes to run on a big endian system
+ *
+ *  This file is subject to the terms and conditions of the GNU General Public
+ *  License. See the file COPYING in the main directory of this archive
+ *  for more details.
+ */
+
+#include <linux/module.h>
+#include <linux/string.h>
+
+#include "c2p.h"
+#include "c2p_core.h"
+
+
+    /*
+     *  Perform a full C2P step on 32 8-bit pixels, stored in 8 32-bit words
+     *  containing
+     *    - 32 8-bit chunky pixels on input
+     *    - permutated planar data (1 plane per 32-bit word) on output
+     */
+
+static void c2p_32x8(u32 d[8])
+{
+	transp8(d, 16, 4);
+	transp8(d, 8, 2);
+	transp8(d, 4, 1);
+	transp8(d, 2, 4);
+	transp8(d, 1, 2);
+}
+
+
+    /*
+     *  Array containing the permutation indices of the planar data after c2p
+     */
+
+static const int perm_c2p_32x8[8] = { 7, 5, 3, 1, 6, 4, 2, 0 };
+
+
+    /*
+     *  Store a full block of planar data after c2p conversion
+     */
+
+static inline void store_planar(void *dst, u32 dst_inc, u32 bpp, u32 d[8])
+{
+	int i;
+
+	for (i = 0; i < bpp; i++, dst += dst_inc)
+		*(u32 *)dst = d[perm_c2p_32x8[i]];
+}
+
+
+    /*
+     *  Store a partial block of planar data after c2p conversion
+     */
+
+static inline void store_planar_masked(void *dst, u32 dst_inc, u32 bpp,
+				       u32 d[8], u32 mask)
+{
+	int i;
+
+	for (i = 0; i < bpp; i++, dst += dst_inc)
+		*(u32 *)dst = comp(d[perm_c2p_32x8[i]], *(u32 *)dst, mask);
+}
+
+
+    /*
+     *  c2p_planar - Copy 8-bit chunky image data to a planar frame buffer
+     *  @dst: Starting address of the planar frame buffer
+     *  @dx: Horizontal destination offset (in pixels)
+     *  @dy: Vertical destination offset (in pixels)
+     *  @width: Image width (in pixels)
+     *  @height: Image height (in pixels)
+     *  @dst_nextline: Frame buffer offset to the next line (in bytes)
+     *  @dst_nextplane: Frame buffer offset to the next plane (in bytes)
+     *  @src_nextline: Image offset to the next line (in bytes)
+     *  @bpp: Bits per pixel of the planar frame buffer (1-8)
+     */
+
+void c2p_planar(void *dst, const void *src, u32 dx, u32 dy, u32 width,
+		u32 height, u32 dst_nextline, u32 dst_nextplane,
+		u32 src_nextline, u32 bpp)
+{
+	union {
+		u8 pixels[32];
+		u32 words[8];
+	} d;
+	u32 dst_idx, first, last, w;
+	const u8 *c;
+	void *p;
+
+	dst += dy*dst_nextline+(dx & ~31);
+	dst_idx = dx % 32;
+	first = 0xffffffffU >> dst_idx;
+	last = ~(0xffffffffU >> ((dst_idx+width) % 32));
+	while (height--) {
+		c = src;
+		p = dst;
+		w = width;
+		if (dst_idx+width <= 32) {
+			/* Single destination word */
+			first &= last;
+			memset(d.pixels, 0, sizeof(d));
+			memcpy(d.pixels+dst_idx, c, width);
+			c += width;
+			c2p_32x8(d.words);
+			store_planar_masked(p, dst_nextplane, bpp, d.words,
+					    first);
+			p += 4;
+		} else {
+			/* Multiple destination words */
+			w = width;
+			/* Leading bits */
+			if (dst_idx) {
+				w = 32 - dst_idx;
+				memset(d.pixels, 0, dst_idx);
+				memcpy(d.pixels+dst_idx, c, w);
+				c += w;
+				c2p_32x8(d.words);
+				store_planar_masked(p, dst_nextplane, bpp,
+						    d.words, first);
+				p += 4;
+				w = width-w;
+			}
+			/* Main chunk */
+			while (w >= 32) {
+				memcpy(d.pixels, c, 32);
+				c += 32;
+				c2p_32x8(d.words);
+				store_planar(p, dst_nextplane, bpp, d.words);
+				p += 4;
+				w -= 32;
+			}
+			/* Trailing bits */
+			w %= 32;
+			if (w > 0) {
+				memcpy(d.pixels, c, w);
+				memset(d.pixels+w, 0, 32-w);
+				c2p_32x8(d.words);
+				store_planar_masked(p, dst_nextplane, bpp,
+						    d.words, last);
+			}
+		}
+		src += src_nextline;
+		dst += dst_nextline;
+	}
+}
+EXPORT_SYMBOL_GPL(c2p_planar);
+
+MODULE_LICENSE("GPL");

-- 
Gr{oetje,eeting}s,

						Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
							    -- Linus Torvalds


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

* Re: [patch 3/6] fbdev: c2p - Cleanups
  2008-12-21 15:01 ` [patch 3/6] fbdev: c2p - Cleanups Geert Uytterhoeven
@ 2008-12-22 23:22   ` Andrew Morton
  2008-12-23  8:13     ` Geert Uytterhoeven
  0 siblings, 1 reply; 12+ messages in thread
From: Andrew Morton @ 2008-12-22 23:22 UTC (permalink / raw)
  To: Geert Uytterhoeven; +Cc: schmitz, linux-fbdev-devel, linux-m68k, linux-kernel

On Sun, 21 Dec 2008 16:01:02 +0100
Geert Uytterhoeven <geert@linux-m68k.org> wrote:

>   - Improve comments and naming
>   - Use void * for arbitrary pointers
>   - Use a union to represent pixels/words, to avoid casts
> 
> Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org>
> ---
>  drivers/video/c2p.c |   80 +++++++++++++++++++++++++++-------------------------
>  drivers/video/c2p.h |    6 +--
>  2 files changed, 45 insertions(+), 41 deletions(-)
> 
> --- a/drivers/video/c2p.c
> +++ b/drivers/video/c2p.c
> @@ -54,7 +54,7 @@ static inline u32 get_mask(int n)
>      return 0;
>  }
>  
> -#define transp_nx1(d, n)				\
> +#define transp8_nx1(d, n)				\
>      do {						\
>  	u32 mask = get_mask(n);				\
>  	/* First block */				\
> @@ -67,7 +67,7 @@ static inline u32 get_mask(int n)
>  	_transp(d, 6, 7, n, mask);			\
>      } while (0)
> -#define transp_nx2(d, n)				\
> +#define transp8_nx2(d, n)				\
>      do {						\
>  	u32 mask = get_mask(n);				\
>  	/* First block */				\
> @@ -78,40 +78,41 @@ static inline u32 get_mask(int n)

I was going to say:

- these don't need to be implemented as macros

- these reference their arguments multiple times and will cause
  problems when passed an expression with side-effects.

- they should be converted to inlined C function, but those functions
  will be waaaaaaaay to big to inline.

but happily, they appear to not have any callers?

>  	_transp(d, 5, 7, n, mask);			\
>      } while (0)
>  
> -#define transp_nx4(d, n)				\
> +#define transp8_nx4(d, n)				\
>      do {						\
>  	u32 mask = get_mask(n);				\
> +	/* Single block */				\
>  	_transp(d, 0, 4, n, mask);			\
>  	_transp(d, 1, 5, n, mask);			\
>  	_transp(d, 2, 6, n, mask);			\
>  	_transp(d, 3, 7, n, mask);			\
>      } while (0)
>  
> -#define transp(d, n, m)	transp_nx ## m(d, n)
> +#define transp8(d, n, m)	transp8_nx ## m(d, n)

ah, yes they do.  Tricky!

>  
>      /*
> @@ -130,12 +131,12 @@ static inline unsigned long comp(unsigne
>       *  Store a full block of planar data after c2p conversion
>       */
>  
> -static inline void store_planar(char *dst, u32 dst_inc, u32 bpp, u32 d[8])
> +static inline void store_planar(void *dst, u32 dst_inc, u32 bpp, u32 d[8])
>  {
>      int i;
>  
>      for (i = 0; i < bpp; i++, dst += dst_inc)
> -	*(u32 *)dst = d[perm_c2p_8bpp[i]];
> +	*(u32 *)dst = d[perm_c2p_32x8[i]];
>  }
>  
>  
> @@ -143,13 +144,13 @@ static inline void store_planar(char *ds
>       *  Store a partial block of planar data after c2p conversion
>       */
>  
> -static inline void store_planar_masked(char *dst, u32 dst_inc, u32 bpp,
> +static inline void store_planar_masked(void *dst, u32 dst_inc, u32 bpp,
>  				       u32 d[8], u32 mask)
>  {
>      int i;
>  
>      for (i = 0; i < bpp; i++, dst += dst_inc)
> -	*(u32 *)dst = comp(d[perm_c2p_8bpp[i]], *(u32 *)dst, mask);
> +	*(u32 *)dst = comp(d[perm_c2p_32x8[i]], *(u32 *)dst, mask);
>  }

This driver needs a inlineectomy.



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

* Re: [patch 6/6] fbdev: c2p - Rename c2p to c2p_planar and correct indentation
  2008-12-21 15:01 ` [patch 6/6] fbdev: c2p - Rename c2p to c2p_planar and correct indentation Geert Uytterhoeven
@ 2008-12-22 23:23   ` Andrew Morton
  2008-12-23  8:02     ` Geert Uytterhoeven
  0 siblings, 1 reply; 12+ messages in thread
From: Andrew Morton @ 2008-12-22 23:23 UTC (permalink / raw)
  To: Geert Uytterhoeven; +Cc: schmitz, linux-fbdev-devel, linux-m68k, linux-kernel

On Sun, 21 Dec 2008 16:01:05 +0100
Geert Uytterhoeven <geert@linux-m68k.org> wrote:

> +    /*
> +     *  Store a full block of planar data after c2p conversion
> +     */
> +
> +static inline void store_planar(void *dst, u32 dst_inc, u32 bpp, u32 d[8])
> +{
> +	int i;
> +
> +	for (i = 0; i < bpp; i++, dst += dst_inc)
> +		*(u32 *)dst = d[perm_c2p_32x8[i]];
> +}
> +
> +
> +    /*
> +     *  Store a partial block of planar data after c2p conversion
> +     */
> +
> +static inline void store_planar_masked(void *dst, u32 dst_inc, u32 bpp,
> +				       u32 d[8], u32 mask)
> +{
> +	int i;
> +
> +	for (i = 0; i < bpp; i++, dst += dst_inc)
> +		*(u32 *)dst = comp(d[perm_c2p_32x8[i]], *(u32 *)dst, mask);
> +}

Why not just make the first arg of these (too large to be inlined)
functions have type u32*, then do away with the casts?


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

* Re: [patch 0/6] [patch 0/6] Atari frame buffer fixes
  2008-12-21 15:00 [patch 0/6] [patch 0/6] Atari frame buffer fixes Geert Uytterhoeven
                   ` (5 preceding siblings ...)
  2008-12-21 15:01 ` [patch 6/6] fbdev: c2p - Rename c2p to c2p_planar and correct indentation Geert Uytterhoeven
@ 2008-12-22 23:24 ` Andrew Morton
  6 siblings, 0 replies; 12+ messages in thread
From: Andrew Morton @ 2008-12-22 23:24 UTC (permalink / raw)
  To: Geert Uytterhoeven; +Cc: schmitz, linux-fbdev-devel, linux-m68k, linux-kernel

On Sun, 21 Dec 2008 16:00:59 +0100
Geert Uytterhoeven <geert@linux-m68k.org> wrote:

> This patchsets contains several fixes for the Atari frame buffer device, and
> includes a refactoring of the c2p (Chunky-to-Planar) code:
>   [1] fbdev: atafb - Fix line length handling
>   [2] fbdev: atafb - Fix 16 bpp console
>   [3] fbdev: c2p - Cleanups
>   [4] fbdev: c2p - Extract common c2p core to c2p_core.h
>   [5] fbdev: c2p/atafb - Add support for Atari interleaved bitplanes
>   [6] fbdev: c2p - Rename c2p to c2p_planar and correct indentation
> 
> If nobody objects, I'd like to push this to Linus via the m68k tree, as the
> c2p code is used by m68k drivers (atafb and amifb) only.
> 

OK by me.

CONFIG_ATAFB_FALCON looks like a serial ATA thing.



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

* Re: [patch 6/6] fbdev: c2p - Rename c2p to c2p_planar and correct indentation
  2008-12-22 23:23   ` Andrew Morton
@ 2008-12-23  8:02     ` Geert Uytterhoeven
  0 siblings, 0 replies; 12+ messages in thread
From: Geert Uytterhoeven @ 2008-12-23  8:02 UTC (permalink / raw)
  To: Andrew Morton; +Cc: schmitz, linux-fbdev-devel, linux-m68k, linux-kernel

On Mon, 22 Dec 2008, Andrew Morton wrote:
> On Sun, 21 Dec 2008 16:01:05 +0100
> Geert Uytterhoeven <geert@linux-m68k.org> wrote:
> 
> > +    /*
> > +     *  Store a full block of planar data after c2p conversion
> > +     */
> > +
> > +static inline void store_planar(void *dst, u32 dst_inc, u32 bpp, u32 d[8])
> > +{
> > +	int i;
> > +
> > +	for (i = 0; i < bpp; i++, dst += dst_inc)
> > +		*(u32 *)dst = d[perm_c2p_32x8[i]];
> > +}
> > +
> > +
> > +    /*
> > +     *  Store a partial block of planar data after c2p conversion
> > +     */
> > +
> > +static inline void store_planar_masked(void *dst, u32 dst_inc, u32 bpp,
> > +				       u32 d[8], u32 mask)
> > +{
> > +	int i;
> > +
> > +	for (i = 0; i < bpp; i++, dst += dst_inc)
> > +		*(u32 *)dst = comp(d[perm_c2p_32x8[i]], *(u32 *)dst, mask);
> > +}
> 
> Why not just make the first arg of these (too large to be inlined)
> functions have type u32*, then do away with the casts?

If I make dst u32 *, then "dst += dst_inc" needs even more ugly casting
(dst_inc is not always a multiple of 4).

Anyway, as it may be an unaligned access, I'll switch to {get,put}_unaligned(),
which has the side effect of hiding the casts.

Gr{oetje,eeting}s,

						Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
							    -- Linus Torvalds

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

* Re: [patch 3/6] fbdev: c2p - Cleanups
  2008-12-22 23:22   ` Andrew Morton
@ 2008-12-23  8:13     ` Geert Uytterhoeven
  0 siblings, 0 replies; 12+ messages in thread
From: Geert Uytterhoeven @ 2008-12-23  8:13 UTC (permalink / raw)
  To: Andrew Morton; +Cc: schmitz, linux-fbdev-devel, linux-m68k, linux-kernel

On Mon, 22 Dec 2008, Andrew Morton wrote:
> On Sun, 21 Dec 2008 16:01:02 +0100
> Geert Uytterhoeven <geert@linux-m68k.org> wrote:
> 
> >   - Improve comments and naming
> >   - Use void * for arbitrary pointers
> >   - Use a union to represent pixels/words, to avoid casts
> > 
> > Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org>
> > ---
> >  drivers/video/c2p.c |   80 +++++++++++++++++++++++++++-------------------------
> >  drivers/video/c2p.h |    6 +--
> >  2 files changed, 45 insertions(+), 41 deletions(-)
> > 
> > --- a/drivers/video/c2p.c
> > +++ b/drivers/video/c2p.c
> > @@ -54,7 +54,7 @@ static inline u32 get_mask(int n)
> >      return 0;
> >  }
> >  
> > -#define transp_nx1(d, n)				\
> > +#define transp8_nx1(d, n)				\
> >      do {						\
> >  	u32 mask = get_mask(n);				\
> >  	/* First block */				\
> > @@ -67,7 +67,7 @@ static inline u32 get_mask(int n)
> >  	_transp(d, 6, 7, n, mask);			\
> >      } while (0)
> > -#define transp_nx2(d, n)				\
> > +#define transp8_nx2(d, n)				\
> >      do {						\
> >  	u32 mask = get_mask(n);				\
> >  	/* First block */				\
> > @@ -78,40 +78,41 @@ static inline u32 get_mask(int n)
> 
> I was going to say:
> 
> - these don't need to be implemented as macros
> 
> - these reference their arguments multiple times and will cause
>   problems when passed an expression with side-effects.

You're right. These could be inline functions.

> - they should be converted to inlined C function, but those functions
>   will be waaaaaaaay to big to inline.

They're actually not _that_ big. And "n" is known at compile-time.

> but happily, they appear to not have any callers?
> 
> >  	_transp(d, 5, 7, n, mask);			\
> >      } while (0)
> >  
> > -#define transp_nx4(d, n)				\
> > +#define transp8_nx4(d, n)				\
> >      do {						\
> >  	u32 mask = get_mask(n);				\
> > +	/* Single block */				\
> >  	_transp(d, 0, 4, n, mask);			\
> >  	_transp(d, 1, 5, n, mask);			\
> >  	_transp(d, 2, 6, n, mask);			\
> >  	_transp(d, 3, 7, n, mask);			\
> >      } while (0)
> >  
> > -#define transp(d, n, m)	transp_nx ## m(d, n)
> > +#define transp8(d, n, m)	transp8_nx ## m(d, n)
> 
> ah, yes they do.  Tricky!

But this macro exist to provide one single transp8(d, n, m) API.
Perhaps it'll work as one big inline function too. I'll check if gcc
is smart enough to optimize it ("m" is known at compile-time, too).

> >      /*
> > @@ -130,12 +131,12 @@ static inline unsigned long comp(unsigne
> >       *  Store a full block of planar data after c2p conversion
> >       */
> >  
> > -static inline void store_planar(char *dst, u32 dst_inc, u32 bpp, u32 d[8])
> > +static inline void store_planar(void *dst, u32 dst_inc, u32 bpp, u32 d[8])
> >  {
> >      int i;
> >  
> >      for (i = 0; i < bpp; i++, dst += dst_inc)
> > -	*(u32 *)dst = d[perm_c2p_8bpp[i]];
> > +	*(u32 *)dst = d[perm_c2p_32x8[i]];
> >  }
> >  
> >  
> > @@ -143,13 +144,13 @@ static inline void store_planar(char *ds
> >       *  Store a partial block of planar data after c2p conversion
> >       */
> >  
> > -static inline void store_planar_masked(char *dst, u32 dst_inc, u32 bpp,
> > +static inline void store_planar_masked(void *dst, u32 dst_inc, u32 bpp,
> >  				       u32 d[8], u32 mask)
> >  {
> >      int i;
> >  
> >      for (i = 0; i < bpp; i++, dst += dst_inc)
> > -	*(u32 *)dst = comp(d[perm_c2p_8bpp[i]], *(u32 *)dst, mask);
> > +	*(u32 *)dst = comp(d[perm_c2p_32x8[i]], *(u32 *)dst, mask);
> >  }
> 
> This driver needs a inlineectomy.

I actually want it to be inlined.

Gr{oetje,eeting}s,

						Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
							    -- Linus Torvalds

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

end of thread, other threads:[~2008-12-23  8:13 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2008-12-21 15:00 [patch 0/6] [patch 0/6] Atari frame buffer fixes Geert Uytterhoeven
2008-12-21 15:01 ` [patch 1/6] fbdev: atafb - Fix line length handling Geert Uytterhoeven
2008-12-21 15:01 ` [patch 2/6] fbdev: atafb - Fix 16 bpp console Geert Uytterhoeven
2008-12-21 15:01 ` [patch 3/6] fbdev: c2p - Cleanups Geert Uytterhoeven
2008-12-22 23:22   ` Andrew Morton
2008-12-23  8:13     ` Geert Uytterhoeven
2008-12-21 15:01 ` [patch 4/6] fbdev: c2p - Extract common c2p core to c2p_core.h Geert Uytterhoeven
2008-12-21 15:01 ` [patch 5/6] fbdev: c2p/atafb - Add support for Atari interleaved bitplanes Geert Uytterhoeven
2008-12-21 15:01 ` [patch 6/6] fbdev: c2p - Rename c2p to c2p_planar and correct indentation Geert Uytterhoeven
2008-12-22 23:23   ` Andrew Morton
2008-12-23  8:02     ` Geert Uytterhoeven
2008-12-22 23:24 ` [patch 0/6] [patch 0/6] Atari frame buffer fixes Andrew Morton

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.