Gerd Hoffmann
2018-Sep-19 11:12 UTC
[PATCH v3 4/5] 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 at redhat.com> --- drivers/gpu/drm/bochs/bochs.h | 4 ++- drivers/gpu/drm/bochs/bochs_fbdev.c | 3 +- drivers/gpu/drm/bochs/bochs_hw.c | 64 +++++++++++++++++++++++++++++-------- drivers/gpu/drm/bochs/bochs_kms.c | 8 +++-- 4 files changed, 61 insertions(+), 18 deletions(-) diff --git a/drivers/gpu/drm/bochs/bochs.h b/drivers/gpu/drm/bochs/bochs.h index b4f6bb5219..e7a69077e4 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 c46fdae44e..dd3c7df267 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 16e4f1cacc..cacff73a64 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 f3fdaf9456..9bc5b438ae 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) -- 2.9.3