diff options
author | Gerd Hoffmann <kraxel@redhat.com> | 2018-09-21 09:47:01 -0400 |
---|---|---|
committer | Gerd Hoffmann <kraxel@redhat.com> | 2018-09-25 08:49:49 -0400 |
commit | 48b442238250bd27edfef13ab314b295b2734cc4 (patch) | |
tree | 6b26575d83c1f75d57e67283e7d15423ce9d95c3 | |
parent | 184bef8924c95d43c1476d21034c14c8582f487f (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.c | 17 | ||||
-rw-r--r-- | drivers/gpu/drm/bochs/bochs_kms.c | 34 |
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 | ||
139 | static struct drm_framebuffer * | ||
140 | bochs_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 | |||
140 | const struct drm_mode_config_funcs bochs_mode_funcs = { | 149 | const 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 | ||
144 | int bochs_fbdev_init(struct bochs_device *bochs) | 153 | int 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 | ||
129 | static const uint32_t bochs_formats[] = { | ||
130 | DRM_FORMAT_HOST_XRGB8888, | ||
131 | }; | ||
132 | |||
133 | static 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 | |||
129 | static void bochs_crtc_init(struct drm_device *dev) | 158 | static 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 | ||