aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGerd Hoffmann <kraxel@redhat.com>2018-09-21 09:47:01 -0400
committerGerd Hoffmann <kraxel@redhat.com>2018-09-25 08:49:49 -0400
commit48b442238250bd27edfef13ab314b295b2734cc4 (patch)
tree6b26575d83c1f75d57e67283e7d15423ce9d95c3
parent184bef8924c95d43c1476d21034c14c8582f487f (diff)
drm/bochs: fix DRM_FORMAT_* handling for big endian machines.
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
-rw-r--r--drivers/gpu/drm/bochs/bochs_fbdev.c17
-rw-r--r--drivers/gpu/drm/bochs/bochs_kms.c34
2 files changed, 46 insertions, 5 deletions
diff --git a/drivers/gpu/drm/bochs/bochs_fbdev.c b/drivers/gpu/drm/bochs/bochs_fbdev.c
index 8f4d6c052f7b..c46fdae44ea3 100644
--- a/drivers/gpu/drm/bochs/bochs_fbdev.c
+++ b/drivers/gpu/drm/bochs/bochs_fbdev.c
@@ -63,9 +63,8 @@ static int bochsfb_create(struct drm_fb_helper *helper,
63 63
64 mode_cmd.width = sizes->surface_width; 64 mode_cmd.width = sizes->surface_width;
65 mode_cmd.height = sizes->surface_height; 65 mode_cmd.height = sizes->surface_height;
66 mode_cmd.pitches[0] = mode_cmd.width * ((sizes->surface_bpp + 7) / 8); 66 mode_cmd.pitches[0] = sizes->surface_width * 4;
67 mode_cmd.pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp, 67 mode_cmd.pixel_format = DRM_FORMAT_HOST_XRGB8888;
68 sizes->surface_depth);
69 size = mode_cmd.pitches[0] * mode_cmd.height; 68 size = mode_cmd.pitches[0] * mode_cmd.height;
70 69
71 /* alloc, pin & map bo */ 70 /* alloc, pin & map bo */
@@ -137,8 +136,18 @@ static const struct drm_fb_helper_funcs bochs_fb_helper_funcs = {
137 .fb_probe = bochsfb_create, 136 .fb_probe = bochsfb_create,
138}; 137};
139 138
139static struct drm_framebuffer *
140bochs_gem_fb_create(struct drm_device *dev, struct drm_file *file,
141 const struct drm_mode_fb_cmd2 *mode_cmd)
142{
143 if (mode_cmd->pixel_format != DRM_FORMAT_HOST_XRGB8888)
144 return ERR_PTR(-EINVAL);
145
146 return drm_gem_fb_create(dev, file, mode_cmd);
147}
148
140const struct drm_mode_config_funcs bochs_mode_funcs = { 149const struct drm_mode_config_funcs bochs_mode_funcs = {
141 .fb_create = drm_gem_fb_create, 150 .fb_create = bochs_gem_fb_create,
142}; 151};
143 152
144int bochs_fbdev_init(struct bochs_device *bochs) 153int bochs_fbdev_init(struct bochs_device *bochs)
diff --git a/drivers/gpu/drm/bochs/bochs_kms.c b/drivers/gpu/drm/bochs/bochs_kms.c
index ea9a43d31bf1..f3fdaf945605 100644
--- a/drivers/gpu/drm/bochs/bochs_kms.c
+++ b/drivers/gpu/drm/bochs/bochs_kms.c
@@ -126,12 +126,43 @@ static const struct drm_crtc_helper_funcs bochs_helper_funcs = {
126 .commit = bochs_crtc_commit, 126 .commit = bochs_crtc_commit,
127}; 127};
128 128
129static const uint32_t bochs_formats[] = {
130 DRM_FORMAT_HOST_XRGB8888,
131};
132
133static struct drm_plane *bochs_primary_plane(struct drm_device *dev)
134{
135 struct drm_plane *primary;
136 int ret;
137
138 primary = kzalloc(sizeof(*primary), GFP_KERNEL);
139 if (primary == NULL) {
140 DRM_DEBUG_KMS("Failed to allocate primary plane\n");
141 return NULL;
142 }
143
144 ret = drm_universal_plane_init(dev, primary, 0,
145 &drm_primary_helper_funcs,
146 bochs_formats,
147 ARRAY_SIZE(bochs_formats),
148 NULL,
149 DRM_PLANE_TYPE_PRIMARY, NULL);
150 if (ret) {
151 kfree(primary);
152 primary = NULL;
153 }
154
155 return primary;
156}
157
129static void bochs_crtc_init(struct drm_device *dev) 158static void bochs_crtc_init(struct drm_device *dev)
130{ 159{
131 struct bochs_device *bochs = dev->dev_private; 160 struct bochs_device *bochs = dev->dev_private;
132 struct drm_crtc *crtc = &bochs->crtc; 161 struct drm_crtc *crtc = &bochs->crtc;
162 struct drm_plane *primary = bochs_primary_plane(dev);
133 163
134 drm_crtc_init(dev, crtc, &bochs_crtc_funcs); 164 drm_crtc_init_with_planes(dev, crtc, primary, NULL,
165 &bochs_crtc_funcs, NULL);
135 drm_crtc_helper_add(crtc, &bochs_helper_funcs); 166 drm_crtc_helper_add(crtc, &bochs_helper_funcs);
136} 167}
137 168
@@ -250,6 +281,7 @@ int bochs_kms_init(struct bochs_device *bochs)
250 bochs->dev->mode_config.fb_base = bochs->fb_base; 281 bochs->dev->mode_config.fb_base = bochs->fb_base;
251 bochs->dev->mode_config.preferred_depth = 24; 282 bochs->dev->mode_config.preferred_depth = 24;
252 bochs->dev->mode_config.prefer_shadow = 0; 283 bochs->dev->mode_config.prefer_shadow = 0;
284 bochs->dev->mode_config.quirk_addfb_prefer_host_byte_order = true;
253 285
254 bochs->dev->mode_config.funcs = &bochs_mode_funcs; 286 bochs->dev->mode_config.funcs = &bochs_mode_funcs;
255 287