diff options
Diffstat (limited to 'drivers/gpu/drm/drm_framebuffer.c')
-rw-r--r-- | drivers/gpu/drm/drm_framebuffer.c | 60 |
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 | ||
375 | int 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 | |||
355 | struct drm_mode_rmfb_work { | 399 | struct 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) |