drm/bochs: fix DRM_FORMAT_* handling for big endian machines.
authorGerd Hoffmann <kraxel@redhat.com>
Fri, 21 Sep 2018 13:47:01 +0000 (15:47 +0200)
committerGerd Hoffmann <kraxel@redhat.com>
Tue, 25 Sep 2018 12:49:49 +0000 (14:49 +0200)
Use DRM_FORMAT_HOST_XRGB8888, so we are using the correct format code
on bigendian machines.  Also set the quirk_addfb_prefer_host_byte_order
mode_config bit so drm_mode_addfb() asks for the correct format code.

Create our own plane and use drm_crtc_init_with_planes() instead of
depending on the default created by drm_crtc_init().  That way the plane
format list is correct on bigendian machines.

Also re-add the framebuffer format check dropped by "df2052cc92 bochs:
convert to drm_fb_helper_fbdev_setup/teardown".

With this patch applied both ADDFB and ADDFB2 ioctls work correctly in
the bochs-drm.ko driver on big endian machines.  Without the patch only
ADDFB (which still seems to be used by the majority of userspace) works
correctly.

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-4-kraxel@redhat.com
drivers/gpu/drm/bochs/bochs_fbdev.c
drivers/gpu/drm/bochs/bochs_kms.c

index 8f4d6c052f7bc86ba61f5d74cba8e019288fa762..c46fdae44ea31b4489a9f760dda1f1fe284cb9b0 100644 (file)
@@ -63,9 +63,8 @@ static int bochsfb_create(struct drm_fb_helper *helper,
 
        mode_cmd.width = sizes->surface_width;
        mode_cmd.height = sizes->surface_height;
-       mode_cmd.pitches[0] = mode_cmd.width * ((sizes->surface_bpp + 7) / 8);
-       mode_cmd.pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp,
-                                                         sizes->surface_depth);
+       mode_cmd.pitches[0] = sizes->surface_width * 4;
+       mode_cmd.pixel_format = DRM_FORMAT_HOST_XRGB8888;
        size = mode_cmd.pitches[0] * mode_cmd.height;
 
        /* alloc, pin & map bo */
@@ -137,8 +136,18 @@ static const struct drm_fb_helper_funcs bochs_fb_helper_funcs = {
        .fb_probe = bochsfb_create,
 };
 
+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)
+               return ERR_PTR(-EINVAL);
+
+       return drm_gem_fb_create(dev, file, mode_cmd);
+}
+
 const struct drm_mode_config_funcs bochs_mode_funcs = {
-       .fb_create = drm_gem_fb_create,
+       .fb_create = bochs_gem_fb_create,
 };
 
 int bochs_fbdev_init(struct bochs_device *bochs)
index ea9a43d31bf1be969b5e3915b67d4e99caada512..f3fdaf94560571ecabe4b9535a0bdbfad5b7d4cf 100644 (file)
@@ -126,12 +126,43 @@ static const struct drm_crtc_helper_funcs bochs_helper_funcs = {
        .commit = bochs_crtc_commit,
 };
 
+static const uint32_t bochs_formats[] = {
+       DRM_FORMAT_HOST_XRGB8888,
+};
+
+static struct drm_plane *bochs_primary_plane(struct drm_device *dev)
+{
+       struct drm_plane *primary;
+       int ret;
+
+       primary = kzalloc(sizeof(*primary), GFP_KERNEL);
+       if (primary == NULL) {
+               DRM_DEBUG_KMS("Failed to allocate primary plane\n");
+               return NULL;
+       }
+
+       ret = drm_universal_plane_init(dev, primary, 0,
+                                      &drm_primary_helper_funcs,
+                                      bochs_formats,
+                                      ARRAY_SIZE(bochs_formats),
+                                      NULL,
+                                      DRM_PLANE_TYPE_PRIMARY, NULL);
+       if (ret) {
+               kfree(primary);
+               primary = NULL;
+       }
+
+       return primary;
+}
+
 static void bochs_crtc_init(struct drm_device *dev)
 {
        struct bochs_device *bochs = dev->dev_private;
        struct drm_crtc *crtc = &bochs->crtc;
+       struct drm_plane *primary = bochs_primary_plane(dev);
 
-       drm_crtc_init(dev, crtc, &bochs_crtc_funcs);
+       drm_crtc_init_with_planes(dev, crtc, primary, NULL,
+                                 &bochs_crtc_funcs, NULL);
        drm_crtc_helper_add(crtc, &bochs_helper_funcs);
 }
 
@@ -250,6 +281,7 @@ int bochs_kms_init(struct bochs_device *bochs)
        bochs->dev->mode_config.fb_base = bochs->fb_base;
        bochs->dev->mode_config.preferred_depth = 24;
        bochs->dev->mode_config.prefer_shadow = 0;
+       bochs->dev->mode_config.quirk_addfb_prefer_host_byte_order = true;
 
        bochs->dev->mode_config.funcs = &bochs_mode_funcs;