Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c88f9f0c authored by Michel Dänzer's avatar Michel Dänzer Committed by Dave Airlie
Browse files

drm/radeon/kms: Use surfaces for scanout / cursor byte swapping on big endian.

parent 733289c2
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -2235,6 +2235,11 @@ int r100_set_surface_reg(struct radeon_device *rdev, int reg,
			flags |= R300_SURF_TILE_MICRO;
	}

	if (tiling_flags & RADEON_TILING_SWAP_16BIT)
		flags |= RADEON_SURF_AP0_SWP_16BPP | RADEON_SURF_AP1_SWP_16BPP;
	if (tiling_flags & RADEON_TILING_SWAP_32BIT)
		flags |= RADEON_SURF_AP0_SWP_32BPP | RADEON_SURF_AP1_SWP_32BPP;

	DRM_DEBUG("writing surface %d %d %x %x\n", reg, flags, offset, offset+obj_size-1);
	WREG32(RADEON_SURFACE0_INFO + surf_index, flags);
	WREG32(RADEON_SURFACE0_LOWER_BOUND + surf_index, offset);
+18 −103
Original line number Diff line number Diff line
@@ -45,71 +45,9 @@ struct radeon_fb_device {
	struct radeon_device		*rdev;
};

static int radeon_fb_check_var(struct fb_var_screeninfo *var,
			       struct fb_info *info)
{
	int ret;
	ret = drm_fb_helper_check_var(var, info);
	if (ret)
		return ret;

	/* big endian override for radeon endian workaround */
#ifdef __BIG_ENDIAN
	{
		int depth;
		switch (var->bits_per_pixel) {
		case 16:
			depth = (var->green.length == 6) ? 16 : 15;
			break;
		case 32:
			depth = (var->transp.length > 0) ? 32 : 24;
			break;
		default:
			depth = var->bits_per_pixel;
			break;
		}
		switch (depth) {
		case 8:
			var->red.offset = 0;
			var->green.offset = 0;
			var->blue.offset = 0;
			var->red.length = 8;
			var->green.length = 8;
			var->blue.length = 8;
			var->transp.length = 0;
			var->transp.offset = 0;
			break;
		case 24:
			var->red.offset = 8;
			var->green.offset = 16;
			var->blue.offset = 24;
			var->red.length = 8;
			var->green.length = 8;
			var->blue.length = 8;
			var->transp.length = 0;
			var->transp.offset = 0;
			break;
		case 32:
			var->red.offset = 8;
			var->green.offset = 16;
			var->blue.offset = 24;
			var->red.length = 8;
			var->green.length = 8;
			var->blue.length = 8;
			var->transp.length = 8;
			var->transp.offset = 0;
			break;
		default:
			return -EINVAL;
		}
	}
#endif
	return 0;
}

static struct fb_ops radeonfb_ops = {
	.owner = THIS_MODULE,
	.fb_check_var = radeon_fb_check_var,
	.fb_check_var = drm_fb_helper_check_var,
	.fb_set_par = drm_fb_helper_set_par,
	.fb_setcolreg = drm_fb_helper_setcolreg,
	.fb_fillrect = cfb_fillrect,
@@ -206,6 +144,7 @@ int radeonfb_create(struct drm_device *dev,
	void *fbptr = NULL;
	unsigned long tmp;
	bool fb_tiled = false; /* useful for testing */
	u32 tiling_flags = 0;

	mode_cmd.width = surface_width;
	mode_cmd.height = surface_height;
@@ -230,7 +169,22 @@ int radeonfb_create(struct drm_device *dev,
	robj = gobj->driver_private;

	if (fb_tiled)
		radeon_object_set_tiling_flags(robj, RADEON_TILING_MACRO|RADEON_TILING_SURFACE, mode_cmd.pitch);
		tiling_flags = RADEON_TILING_MACRO;

#ifdef __BIG_ENDIAN
	switch (mode_cmd.bpp) {
	case 32:
		tiling_flags |= RADEON_TILING_SWAP_32BIT;
		break;
	case 16:
		tiling_flags |= RADEON_TILING_SWAP_16BIT;
	default:
		break;
	}
#endif

	if (tiling_flags)
		radeon_object_set_tiling_flags(robj, tiling_flags | RADEON_TILING_SURFACE, mode_cmd.pitch);
	mutex_lock(&rdev->ddev->struct_mutex);
	fb = radeon_framebuffer_create(rdev->ddev, &mode_cmd, gobj);
	if (fb == NULL) {
@@ -313,45 +267,6 @@ int radeonfb_create(struct drm_device *dev,
	DRM_INFO("fb depth is %d\n", fb->depth);
	DRM_INFO("   pitch is %d\n", fb->pitch);

#ifdef __BIG_ENDIAN
	/* fill var sets defaults for this stuff - override
	   on big endian */
	switch (fb->depth) {
	case 8:
		info->var.red.offset = 0;
		info->var.green.offset = 0;
		info->var.blue.offset = 0;
		info->var.red.length = 8; /* 8bit DAC */
		info->var.green.length = 8;
		info->var.blue.length = 8;
		info->var.transp.offset = 0;
		info->var.transp.length = 0;
		break;
	case 24:
		info->var.red.offset = 8;
		info->var.green.offset = 16;
		info->var.blue.offset = 24;
		info->var.red.length = 8;
		info->var.green.length = 8;
		info->var.blue.length = 8;
		info->var.transp.offset = 0;
		info->var.transp.length = 0;
		break;
	case 32:
		info->var.red.offset = 8;
		info->var.green.offset = 16;
		info->var.blue.offset = 24;
		info->var.red.length = 8;
		info->var.green.length = 8;
		info->var.blue.length = 8;
		info->var.transp.offset = 0;
		info->var.transp.length = 8;
		break;
	default:
		break;
	}
#endif

	fb->fbdev = info;
	rfbdev->rfb = rfb;
	rfbdev->rdev = rdev;
+2 −0
Original line number Diff line number Diff line
@@ -188,6 +188,7 @@ int radeon_object_kmap(struct radeon_object *robj, void **ptr)
	if (ptr) {
		*ptr = robj->kptr;
	}
	radeon_object_check_tiling(robj, 0, 0);
	return 0;
}

@@ -200,6 +201,7 @@ void radeon_object_kunmap(struct radeon_object *robj)
	}
	robj->kptr = NULL;
	spin_unlock(&robj->tobj.lock);
	radeon_object_check_tiling(robj, 0, 0);
	ttm_bo_kunmap(&robj->kmap);
}

+6 −5
Original line number Diff line number Diff line
@@ -804,8 +804,9 @@ struct drm_radeon_gem_create {

#define RADEON_TILING_MACRO       0x1
#define RADEON_TILING_MICRO       0x2
#define RADEON_TILING_SWAP  0x4
#define RADEON_TILING_SURFACE  0x8 /* this object requires a surface
#define RADEON_TILING_SWAP_16BIT  0x4
#define RADEON_TILING_SWAP_32BIT  0x8
#define RADEON_TILING_SURFACE     0x10 /* this object requires a surface
					* when mapped - i.e. front buffer */

struct drm_radeon_gem_set_tiling {