aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/drm_framebuffer.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/drm_framebuffer.c')
-rw-r--r--drivers/gpu/drm/drm_framebuffer.c60
1 files changed, 52 insertions, 8 deletions
diff --git a/drivers/gpu/drm/drm_framebuffer.c b/drivers/gpu/drm/drm_framebuffer.c
index 781af1d42d76..1ee3d6b44280 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,37 @@ 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 if (!drm_core_check_feature(dev, DRIVER_MODESET))
117 return -EOPNOTSUPP;
118
119 r.pixel_format = drm_mode_legacy_fb_format(or->bpp, or->depth);
120 if (r.pixel_format == DRM_FORMAT_INVALID) {
121 DRM_DEBUG("bad {bpp:%d, depth:%d}\n", or->bpp, or->depth);
122 return -EINVAL;
123 }
124
115 /* convert to new format and call new ioctl */ 125 /* convert to new format and call new ioctl */
116 r.fb_id = or->fb_id; 126 r.fb_id = or->fb_id;
117 r.width = or->width; 127 r.width = or->width;
118 r.height = or->height; 128 r.height = or->height;
119 r.pitches[0] = or->pitch; 129 r.pitches[0] = or->pitch;
120 r.pixel_format = drm_mode_legacy_fb_format(or->bpp, or->depth);
121 r.handles[0] = or->handle; 130 r.handles[0] = or->handle;
122 131
123 if (r.pixel_format == DRM_FORMAT_XRGB2101010 && 132 if (dev->mode_config.quirk_addfb_prefer_xbgr_30bpp &&
124 dev->driver->driver_features & DRIVER_PREFER_XBGR_30BPP) 133 r.pixel_format == DRM_FORMAT_XRGB2101010)
125 r.pixel_format = DRM_FORMAT_XBGR2101010; 134 r.pixel_format = DRM_FORMAT_XBGR2101010;
126 135
136 if (dev->mode_config.quirk_addfb_prefer_host_byte_order) {
137 if (r.pixel_format == DRM_FORMAT_XRGB8888)
138 r.pixel_format = DRM_FORMAT_HOST_XRGB8888;
139 if (r.pixel_format == DRM_FORMAT_ARGB8888)
140 r.pixel_format = DRM_FORMAT_HOST_ARGB8888;
141 if (r.pixel_format == DRM_FORMAT_RGB565)
142 r.pixel_format = DRM_FORMAT_HOST_RGB565;
143 if (r.pixel_format == DRM_FORMAT_XRGB1555)
144 r.pixel_format = DRM_FORMAT_HOST_XRGB1555;
145 }
146
127 ret = drm_mode_addfb2(dev, &r, file_priv); 147 ret = drm_mode_addfb2(dev, &r, file_priv);
128 if (ret) 148 if (ret)
129 return ret; 149 return ret;
@@ -164,7 +184,7 @@ static int framebuffer_check(struct drm_device *dev,
164 int i; 184 int i;
165 185
166 /* check if the format is supported at all */ 186 /* check if the format is supported at all */
167 info = __drm_format_info(r->pixel_format & ~DRM_FORMAT_BIG_ENDIAN); 187 info = __drm_format_info(r->pixel_format);
168 if (!info) { 188 if (!info) {
169 struct drm_format_name_buf format_name; 189 struct drm_format_name_buf format_name;
170 190
@@ -335,7 +355,7 @@ int drm_mode_addfb2(struct drm_device *dev,
335 struct drm_framebuffer *fb; 355 struct drm_framebuffer *fb;
336 356
337 if (!drm_core_check_feature(dev, DRIVER_MODESET)) 357 if (!drm_core_check_feature(dev, DRIVER_MODESET))
338 return -EINVAL; 358 return -EOPNOTSUPP;
339 359
340 fb = drm_internal_framebuffer_create(dev, r, file_priv); 360 fb = drm_internal_framebuffer_create(dev, r, file_priv);
341 if (IS_ERR(fb)) 361 if (IS_ERR(fb))
@@ -352,6 +372,30 @@ int drm_mode_addfb2(struct drm_device *dev,
352 return 0; 372 return 0;
353} 373}
354 374
375int drm_mode_addfb2_ioctl(struct drm_device *dev,
376 void *data, struct drm_file *file_priv)
377{
378#ifdef __BIG_ENDIAN
379 if (!dev->mode_config.quirk_addfb_prefer_host_byte_order) {
380 /*
381 * Drivers must set the
382 * quirk_addfb_prefer_host_byte_order quirk to make
383 * the drm_mode_addfb() compat code work correctly on
384 * bigendian machines.
385 *
386 * If they don't they interpret pixel_format values
387 * incorrectly for bug compatibility, which in turn
388 * implies the ADDFB2 ioctl does not work correctly
389 * then. So block it to make userspace fallback to
390 * ADDFB.
391 */
392 DRM_DEBUG_KMS("addfb2 broken on bigendian");
393 return -EOPNOTSUPP;
394 }
395#endif
396 return drm_mode_addfb2(dev, data, file_priv);
397}
398
355struct drm_mode_rmfb_work { 399struct drm_mode_rmfb_work {
356 struct work_struct work; 400 struct work_struct work;
357 struct list_head fbs; 401 struct list_head fbs;
@@ -391,7 +435,7 @@ int drm_mode_rmfb(struct drm_device *dev, u32 fb_id,
391 int found = 0; 435 int found = 0;
392 436
393 if (!drm_core_check_feature(dev, DRIVER_MODESET)) 437 if (!drm_core_check_feature(dev, DRIVER_MODESET))
394 return -EINVAL; 438 return -EOPNOTSUPP;
395 439
396 fb = drm_framebuffer_lookup(dev, file_priv, fb_id); 440 fb = drm_framebuffer_lookup(dev, file_priv, fb_id);
397 if (!fb) 441 if (!fb)
@@ -468,7 +512,7 @@ int drm_mode_getfb(struct drm_device *dev,
468 int ret; 512 int ret;
469 513
470 if (!drm_core_check_feature(dev, DRIVER_MODESET)) 514 if (!drm_core_check_feature(dev, DRIVER_MODESET))
471 return -EINVAL; 515 return -EOPNOTSUPP;
472 516
473 fb = drm_framebuffer_lookup(dev, file_priv, r->fb_id); 517 fb = drm_framebuffer_lookup(dev, file_priv, r->fb_id);
474 if (!fb) 518 if (!fb)
@@ -541,7 +585,7 @@ int drm_mode_dirtyfb_ioctl(struct drm_device *dev,
541 int ret; 585 int ret;
542 586
543 if (!drm_core_check_feature(dev, DRIVER_MODESET)) 587 if (!drm_core_check_feature(dev, DRIVER_MODESET))
544 return -EINVAL; 588 return -EOPNOTSUPP;
545 589
546 fb = drm_framebuffer_lookup(dev, file_priv, r->fb_id); 590 fb = drm_framebuffer_lookup(dev, file_priv, r->fb_id);
547 if (!fb) 591 if (!fb)