radeonfb: fix problem with color expansion & alignment

The engine on some radeon variants locks up if color expansion is called
for non aligned source data. This patch enables a feature of the core
fbdev to request aligned input pixmaps and uses the HW clipping engine to
clip the output to the requested size

Addresses http://bugzilla.kernel.org/show_bug.cgi?id=11875

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Tested-by: James Cloos <cloos@jhcloos.com>
Cc: "Rafael J. Wysocki" <rjw@sisk.pl>
Cc: "David S. Miller" <davem@davemloft.net>
Cc: Krzysztof Helt <krzysztof.h1@poczta.fm>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

authored by Benjamin Herrenschmidt and committed by Linus Torvalds c4c6fa98 b93c35ff

+30 -9
+12 -9
drivers/video/aty/radeon_accel.c
··· 174 174 const struct fb_image *image, 175 175 u32 fg, u32 bg) 176 176 { 177 - unsigned int src_bytes, dwords; 177 + unsigned int dwords; 178 178 u32 *bits; 179 179 180 180 radeonfb_set_creg(rinfo, DP_GUI_MASTER_CNTL, &rinfo->dp_gui_mc_cache, 181 181 rinfo->dp_gui_mc_base | 182 - GMC_BRUSH_NONE | 182 + GMC_BRUSH_NONE | GMC_DST_CLIP_LEAVE | 183 183 GMC_SRC_DATATYPE_MONO_FG_BG | 184 184 ROP3_S | 185 185 GMC_BYTE_ORDER_MSB_TO_LSB | ··· 188 188 DST_X_LEFT_TO_RIGHT | DST_Y_TOP_TO_BOTTOM); 189 189 radeonfb_set_creg(rinfo, DP_SRC_FRGD_CLR, &rinfo->dp_src_fg_cache, fg); 190 190 radeonfb_set_creg(rinfo, DP_SRC_BKGD_CLR, &rinfo->dp_src_bg_cache, bg); 191 - 192 - radeon_fifo_wait(rinfo, 1); 193 - OUTREG(DST_Y_X, (image->dy << 16) | image->dx); 194 191 195 192 /* Ensure the dst cache is flushed and the engine idle before 196 193 * issuing the operation. ··· 202 205 203 206 /* X here pads width to a multiple of 32 and uses the clipper to 204 207 * adjust the result. Is that really necessary ? Things seem to 205 - * work ok for me without that and the doco doesn't seem to imply 208 + * work ok for me without that and the doco doesn't seem to imply] 206 209 * there is such a restriction. 207 210 */ 208 - OUTREG(DST_WIDTH_HEIGHT, (image->width << 16) | image->height); 211 + radeon_fifo_wait(rinfo, 4); 212 + OUTREG(SC_TOP_LEFT, (image->dy << 16) | image->dx); 213 + OUTREG(SC_BOTTOM_RIGHT, ((image->dy + image->height) << 16) | 214 + (image->dx + image->width)); 215 + OUTREG(DST_Y_X, (image->dy << 16) | image->dx); 209 216 210 - src_bytes = (((image->width * image->depth) + 7) / 8) * image->height; 211 - dwords = (src_bytes + 3) / 4; 217 + OUTREG(DST_HEIGHT_WIDTH, (image->height << 16) | ((image->width + 31) & ~31)); 218 + 219 + dwords = (image->width + 31) >> 5; 220 + dwords *= image->height; 212 221 bits = (u32*)(image->data); 213 222 214 223 while(dwords >= 8) {
+18
drivers/video/aty/radeon_base.c
··· 1875 1875 info->fbops = &radeonfb_ops; 1876 1876 info->screen_base = rinfo->fb_base; 1877 1877 info->screen_size = rinfo->mapped_vram; 1878 + 1878 1879 /* Fill fix common fields */ 1879 1880 strlcpy(info->fix.id, rinfo->name, sizeof(info->fix.id)); 1880 1881 info->fix.smem_start = rinfo->fb_base_phys; ··· 1890 1889 info->fix.mmio_len = RADEON_REGSIZE; 1891 1890 info->fix.accel = FB_ACCEL_ATI_RADEON; 1892 1891 1892 + /* Allocate colormap */ 1893 1893 fb_alloc_cmap(&info->cmap, 256, 0); 1894 1894 1895 + /* Setup pixmap used for acceleration */ 1896 + #define PIXMAP_SIZE (2048 * 4) 1897 + 1898 + info->pixmap.addr = kmalloc(PIXMAP_SIZE, GFP_KERNEL); 1899 + if (!info->pixmap.addr) { 1900 + printk(KERN_ERR "radeonfb: Failed to allocate pixmap !\n"); 1901 + noaccel = 1; 1902 + goto bail; 1903 + } 1904 + info->pixmap.size = PIXMAP_SIZE; 1905 + info->pixmap.flags = FB_PIXMAP_SYSTEM; 1906 + info->pixmap.scan_align = 4; 1907 + info->pixmap.buf_align = 4; 1908 + info->pixmap.access_align = 32; 1909 + 1910 + bail: 1895 1911 if (noaccel) 1896 1912 info->flags |= FBINFO_HWACCEL_DISABLED; 1897 1913