diff options
Diffstat (limited to 'drivers/gpu/drm/drm_framebuffer.c')
-rw-r--r-- | drivers/gpu/drm/drm_framebuffer.c | 49 |
1 files changed, 45 insertions, 4 deletions
diff --git a/drivers/gpu/drm/drm_framebuffer.c b/drivers/gpu/drm/drm_framebuffer.c index 781af1d42d76..6eaacd4eb8cc 100644 --- a/drivers/gpu/drm/drm_framebuffer.c +++ b/drivers/gpu/drm/drm_framebuffer.c | |||
@@ -25,6 +25,7 @@ | |||
25 | #include <drm/drm_auth.h> | 25 | #include <drm/drm_auth.h> |
26 | #include <drm/drm_framebuffer.h> | 26 | #include <drm/drm_framebuffer.h> |
27 | #include <drm/drm_atomic.h> | 27 | #include <drm/drm_atomic.h> |
28 | #include <drm/drm_atomic_uapi.h> | ||
28 | #include <drm/drm_print.h> | 29 | #include <drm/drm_print.h> |
29 | 30 | ||
30 | #include "drm_internal.h" | 31 | #include "drm_internal.h" |
@@ -112,18 +113,34 @@ int drm_mode_addfb(struct drm_device *dev, struct drm_mode_fb_cmd *or, | |||
112 | struct drm_mode_fb_cmd2 r = {}; | 113 | struct drm_mode_fb_cmd2 r = {}; |
113 | int ret; | 114 | int ret; |
114 | 115 | ||
116 | r.pixel_format = drm_mode_legacy_fb_format(or->bpp, or->depth); | ||
117 | if (r.pixel_format == DRM_FORMAT_INVALID) { | ||
118 | DRM_DEBUG("bad {bpp:%d, depth:%d}\n", or->bpp, or->depth); | ||
119 | return -EINVAL; | ||
120 | } | ||
121 | |||
115 | /* convert to new format and call new ioctl */ | 122 | /* convert to new format and call new ioctl */ |
116 | r.fb_id = or->fb_id; | 123 | r.fb_id = or->fb_id; |
117 | r.width = or->width; | 124 | r.width = or->width; |
118 | r.height = or->height; | 125 | r.height = or->height; |
119 | r.pitches[0] = or->pitch; | 126 | r.pitches[0] = or->pitch; |
120 | r.pixel_format = drm_mode_legacy_fb_format(or->bpp, or->depth); | ||
121 | r.handles[0] = or->handle; | 127 | r.handles[0] = or->handle; |
122 | 128 | ||
123 | if (r.pixel_format == DRM_FORMAT_XRGB2101010 && | 129 | if (dev->mode_config.quirk_addfb_prefer_xbgr_30bpp && |
124 | dev->driver->driver_features & DRIVER_PREFER_XBGR_30BPP) | 130 | r.pixel_format == DRM_FORMAT_XRGB2101010) |
125 | r.pixel_format = DRM_FORMAT_XBGR2101010; | 131 | r.pixel_format = DRM_FORMAT_XBGR2101010; |
126 | 132 | ||
133 | if (dev->mode_config.quirk_addfb_prefer_host_byte_order) { | ||
134 | if (r.pixel_format == DRM_FORMAT_XRGB8888) | ||
135 | r.pixel_format = DRM_FORMAT_HOST_XRGB8888; | ||
136 | if (r.pixel_format == DRM_FORMAT_ARGB8888) | ||
137 | r.pixel_format = DRM_FORMAT_HOST_ARGB8888; | ||
138 | if (r.pixel_format == DRM_FORMAT_RGB565) | ||
139 | r.pixel_format = DRM_FORMAT_HOST_RGB565; | ||
140 | if (r.pixel_format == DRM_FORMAT_XRGB1555) | ||
141 | r.pixel_format = DRM_FORMAT_HOST_XRGB1555; | ||
142 | } | ||
143 | |||
127 | ret = drm_mode_addfb2(dev, &r, file_priv); | 144 | ret = drm_mode_addfb2(dev, &r, file_priv); |
128 | if (ret) | 145 | if (ret) |
129 | return ret; | 146 | return ret; |
@@ -164,7 +181,7 @@ static int framebuffer_check(struct drm_device *dev, | |||
164 | int i; | 181 | int i; |
165 | 182 | ||
166 | /* check if the format is supported at all */ | 183 | /* check if the format is supported at all */ |
167 | info = __drm_format_info(r->pixel_format & ~DRM_FORMAT_BIG_ENDIAN); | 184 | info = __drm_format_info(r->pixel_format); |
168 | if (!info) { | 185 | if (!info) { |
169 | struct drm_format_name_buf format_name; | 186 | struct drm_format_name_buf format_name; |
170 | 187 | ||
@@ -352,6 +369,30 @@ int drm_mode_addfb2(struct drm_device *dev, | |||
352 | return 0; | 369 | return 0; |
353 | } | 370 | } |
354 | 371 | ||
372 | int drm_mode_addfb2_ioctl(struct drm_device *dev, | ||
373 | void *data, struct drm_file *file_priv) | ||
374 | { | ||
375 | #ifdef __BIG_ENDIAN | ||
376 | if (!dev->mode_config.quirk_addfb_prefer_host_byte_order) { | ||
377 | /* | ||
378 | * Drivers must set the | ||
379 | * quirk_addfb_prefer_host_byte_order quirk to make | ||
380 | * the drm_mode_addfb() compat code work correctly on | ||
381 | * bigendian machines. | ||
382 | * | ||
383 | * If they don't they interpret pixel_format values | ||
384 | * incorrectly for bug compatibility, which in turn | ||
385 | * implies the ADDFB2 ioctl does not work correctly | ||
386 | * then. So block it to make userspace fallback to | ||
387 | * ADDFB. | ||
388 | */ | ||
389 | DRM_DEBUG_KMS("addfb2 broken on bigendian"); | ||
390 | return -EINVAL; | ||
391 | } | ||
392 | #endif | ||
393 | return drm_mode_addfb2(dev, data, file_priv); | ||
394 | } | ||
395 | |||
355 | struct drm_mode_rmfb_work { | 396 | struct drm_mode_rmfb_work { |
356 | struct work_struct work; | 397 | struct work_struct work; |
357 | struct list_head fbs; | 398 | struct list_head fbs; |