drm/bochs: support changing byteorder at mode set time
authorGerd Hoffmann <kraxel@redhat.com>
Fri, 21 Sep 2018 13:47:02 +0000 (15:47 +0200)
committerGerd Hoffmann <kraxel@redhat.com>
Tue, 25 Sep 2018 12:49:49 +0000 (14:49 +0200)
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
drivers/gpu/drm/bochs/bochs.h
drivers/gpu/drm/bochs/bochs_fbdev.c
drivers/gpu/drm/bochs/bochs_hw.c
drivers/gpu/drm/bochs/bochs_kms.c

index b4f6bb5219004bdbe7f8efe3735be225b50aed86..e7a69077e45adfa15431fdb8bb89d6d00c420541 100644 (file)
@@ -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);
 
index c46fdae44ea31b4489a9f760dda1f1fe284cb9b0..dd3c7df267da40cd08cf7e4c1f3795689b1c6462 100644 (file)
@@ -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);
index 16e4f1caccca52ea344b9f4f05b783ae15769e63..cacff73a64abf15fc67790521914b75074df9969 100644 (file)
@@ -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,
index f3fdaf94560571ecabe4b9535a0bdbfad5b7d4cf..9bc5b438aefdb342bde508ece4cf46bde7c97592 100644 (file)
@@ -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)