aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/bochs
diff options
context:
space:
mode:
authorGerd Hoffmann <kraxel@redhat.com>2018-09-21 15:47:02 +0200
committerGerd Hoffmann <kraxel@redhat.com>2018-09-25 14:49:49 +0200
commit86351de023dd3607b1b519f58c11154b217ec031 (patch)
treedf5497c3c4f787e29a62bd0b1df7c1812311374c /drivers/gpu/drm/bochs
parentdrm/bochs: fix DRM_FORMAT_* handling for big endian machines. (diff)
downloadlinux-dev-86351de023dd3607b1b519f58c11154b217ec031.tar.xz
linux-dev-86351de023dd3607b1b519f58c11154b217ec031.zip
drm/bochs: support changing byteorder at mode set time
Add bochs_hw_set_*_endian() helper functions, to set the framebuffer byteorder at mode set time. Support both DRM_FORMAT_XRGB8888 and DRM_FORMAT_BGRX8888 framebuffer formats, no matter what the native machine byte order is. Signed-off-by: Gerd Hoffmann <kraxel@redhat.com> Acked-by: Daniel Vetter <daniel.vetter@ffwll.ch> Link: http://patchwork.freedesktop.org/patch/msgid/20180921134704.12826-5-kraxel@redhat.com
Diffstat (limited to 'drivers/gpu/drm/bochs')
-rw-r--r--drivers/gpu/drm/bochs/bochs.h4
-rw-r--r--drivers/gpu/drm/bochs/bochs_fbdev.c3
-rw-r--r--drivers/gpu/drm/bochs/bochs_hw.c64
-rw-r--r--drivers/gpu/drm/bochs/bochs_kms.c8
4 files changed, 61 insertions, 18 deletions
diff --git a/drivers/gpu/drm/bochs/bochs.h b/drivers/gpu/drm/bochs/bochs.h
index b4f6bb521900..e7a69077e45a 100644
--- a/drivers/gpu/drm/bochs/bochs.h
+++ b/drivers/gpu/drm/bochs/bochs.h
@@ -58,6 +58,7 @@ struct bochs_device {
void __iomem *fb_map;
unsigned long fb_base;
unsigned long fb_size;
+ unsigned long qext_size;
/* mode */
u16 xres;
@@ -121,7 +122,8 @@ int bochs_hw_init(struct drm_device *dev);
void bochs_hw_fini(struct drm_device *dev);
void bochs_hw_setmode(struct bochs_device *bochs,
- struct drm_display_mode *mode);
+ struct drm_display_mode *mode,
+ const struct drm_format_info *format);
void bochs_hw_setbase(struct bochs_device *bochs,
int x, int y, u64 addr);
diff --git a/drivers/gpu/drm/bochs/bochs_fbdev.c b/drivers/gpu/drm/bochs/bochs_fbdev.c
index c46fdae44ea3..dd3c7df267da 100644
--- a/drivers/gpu/drm/bochs/bochs_fbdev.c
+++ b/drivers/gpu/drm/bochs/bochs_fbdev.c
@@ -140,7 +140,8 @@ static struct drm_framebuffer *
bochs_gem_fb_create(struct drm_device *dev, struct drm_file *file,
const struct drm_mode_fb_cmd2 *mode_cmd)
{
- if (mode_cmd->pixel_format != DRM_FORMAT_HOST_XRGB8888)
+ if (mode_cmd->pixel_format != DRM_FORMAT_XRGB8888 &&
+ mode_cmd->pixel_format != DRM_FORMAT_BGRX8888)
return ERR_PTR(-EINVAL);
return drm_gem_fb_create(dev, file, mode_cmd);
diff --git a/drivers/gpu/drm/bochs/bochs_hw.c b/drivers/gpu/drm/bochs/bochs_hw.c
index 16e4f1caccca..cacff73a64ab 100644
--- a/drivers/gpu/drm/bochs/bochs_hw.c
+++ b/drivers/gpu/drm/bochs/bochs_hw.c
@@ -47,11 +47,33 @@ static void bochs_dispi_write(struct bochs_device *bochs, u16 reg, u16 val)
}
}
+static void bochs_hw_set_big_endian(struct bochs_device *bochs)
+{
+ if (bochs->qext_size < 8)
+ return;
+
+ writel(0xbebebebe, bochs->mmio + 0x604);
+}
+
+static void bochs_hw_set_little_endian(struct bochs_device *bochs)
+{
+ if (bochs->qext_size < 8)
+ return;
+
+ writel(0x1e1e1e1e, bochs->mmio + 0x604);
+}
+
+#ifdef __BIG_ENDIAN
+#define bochs_hw_set_native_endian(_b) bochs_hw_set_big_endian(_b)
+#else
+#define bochs_hw_set_native_endian(_b) bochs_hw_set_little_endian(_b)
+#endif
+
int bochs_hw_init(struct drm_device *dev)
{
struct bochs_device *bochs = dev->dev_private;
struct pci_dev *pdev = dev->pdev;
- unsigned long addr, size, mem, ioaddr, iosize, qext_size;
+ unsigned long addr, size, mem, ioaddr, iosize;
u16 id;
if (pdev->resource[2].flags & IORESOURCE_MEM) {
@@ -117,19 +139,14 @@ int bochs_hw_init(struct drm_device *dev)
ioaddr);
if (bochs->mmio && pdev->revision >= 2) {
- qext_size = readl(bochs->mmio + 0x600);
- if (qext_size < 4 || qext_size > iosize)
+ bochs->qext_size = readl(bochs->mmio + 0x600);
+ if (bochs->qext_size < 4 || bochs->qext_size > iosize) {
+ bochs->qext_size = 0;
goto noext;
- DRM_DEBUG("Found qemu ext regs, size %ld\n", qext_size);
- if (qext_size >= 8) {
-#ifdef __BIG_ENDIAN
- writel(0xbebebebe, bochs->mmio + 0x604);
-#else
- writel(0x1e1e1e1e, bochs->mmio + 0x604);
-#endif
- DRM_DEBUG(" qext endian: 0x%x\n",
- readl(bochs->mmio + 0x604));
}
+ DRM_DEBUG("Found qemu ext regs, size %ld\n",
+ bochs->qext_size);
+ bochs_hw_set_native_endian(bochs);
}
noext:
@@ -150,7 +167,8 @@ void bochs_hw_fini(struct drm_device *dev)
}
void bochs_hw_setmode(struct bochs_device *bochs,
- struct drm_display_mode *mode)
+ struct drm_display_mode *mode,
+ const struct drm_format_info *format)
{
bochs->xres = mode->hdisplay;
bochs->yres = mode->vdisplay;
@@ -158,8 +176,12 @@ void bochs_hw_setmode(struct bochs_device *bochs,
bochs->stride = mode->hdisplay * (bochs->bpp / 8);
bochs->yres_virtual = bochs->fb_size / bochs->stride;
- DRM_DEBUG_DRIVER("%dx%d @ %d bpp, vy %d\n",
+ DRM_DEBUG_DRIVER("%dx%d @ %d bpp, format %c%c%c%c, vy %d\n",
bochs->xres, bochs->yres, bochs->bpp,
+ (format->format >> 0) & 0xff,
+ (format->format >> 8) & 0xff,
+ (format->format >> 16) & 0xff,
+ (format->format >> 24) & 0xff,
bochs->yres_virtual);
bochs_vga_writeb(bochs, 0x3c0, 0x20); /* unblank */
@@ -177,6 +199,20 @@ void bochs_hw_setmode(struct bochs_device *bochs,
bochs_dispi_write(bochs, VBE_DISPI_INDEX_ENABLE,
VBE_DISPI_ENABLED | VBE_DISPI_LFB_ENABLED);
+
+ switch (format->format) {
+ case DRM_FORMAT_XRGB8888:
+ bochs_hw_set_little_endian(bochs);
+ break;
+ case DRM_FORMAT_BGRX8888:
+ bochs_hw_set_big_endian(bochs);
+ break;
+ default:
+ /* should not happen */
+ DRM_ERROR("%s: Huh? Got framebuffer format 0x%x",
+ __func__, format->format);
+ break;
+ };
}
void bochs_hw_setbase(struct bochs_device *bochs,
diff --git a/drivers/gpu/drm/bochs/bochs_kms.c b/drivers/gpu/drm/bochs/bochs_kms.c
index f3fdaf945605..9bc5b438aefd 100644
--- a/drivers/gpu/drm/bochs/bochs_kms.c
+++ b/drivers/gpu/drm/bochs/bochs_kms.c
@@ -77,7 +77,10 @@ static int bochs_crtc_mode_set(struct drm_crtc *crtc,
struct bochs_device *bochs =
container_of(crtc, struct bochs_device, crtc);
- bochs_hw_setmode(bochs, mode);
+ if (WARN_ON(crtc->primary->fb == NULL))
+ return -EINVAL;
+
+ bochs_hw_setmode(bochs, mode, crtc->primary->fb->format);
bochs_crtc_mode_set_base(crtc, x, y, old_fb);
return 0;
}
@@ -127,7 +130,8 @@ static const struct drm_crtc_helper_funcs bochs_helper_funcs = {
};
static const uint32_t bochs_formats[] = {
- DRM_FORMAT_HOST_XRGB8888,
+ DRM_FORMAT_XRGB8888,
+ DRM_FORMAT_BGRX8888,
};
static struct drm_plane *bochs_primary_plane(struct drm_device *dev)