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.c194
1 files changed, 88 insertions, 106 deletions
diff --git a/drivers/gpu/drm/drm_framebuffer.c b/drivers/gpu/drm/drm_framebuffer.c
index 398efd67cb93..28a0108a1ab8 100644
--- a/drivers/gpu/drm/drm_framebuffer.c
+++ b/drivers/gpu/drm/drm_framebuffer.c
@@ -39,13 +39,13 @@
39 * Frame buffers rely on the underlying memory manager for allocating backing 39 * Frame buffers rely on the underlying memory manager for allocating backing
40 * storage. When creating a frame buffer applications pass a memory handle 40 * storage. When creating a frame buffer applications pass a memory handle
41 * (or a list of memory handles for multi-planar formats) through the 41 * (or a list of memory handles for multi-planar formats) through the
42 * struct &drm_mode_fb_cmd2 argument. For drivers using GEM as their userspace 42 * &struct drm_mode_fb_cmd2 argument. For drivers using GEM as their userspace
43 * buffer management interface this would be a GEM handle. Drivers are however 43 * buffer management interface this would be a GEM handle. Drivers are however
44 * free to use their own backing storage object handles, e.g. vmwgfx directly 44 * free to use their own backing storage object handles, e.g. vmwgfx directly
45 * exposes special TTM handles to userspace and so expects TTM handles in the 45 * exposes special TTM handles to userspace and so expects TTM handles in the
46 * create ioctl and not GEM handles. 46 * create ioctl and not GEM handles.
47 * 47 *
48 * Framebuffers are tracked with struct &drm_framebuffer. They are published 48 * Framebuffers are tracked with &struct drm_framebuffer. They are published
49 * using drm_framebuffer_init() - after calling that function userspace can use 49 * using drm_framebuffer_init() - after calling that function userspace can use
50 * and access the framebuffer object. The helper function 50 * and access the framebuffer object. The helper function
51 * drm_helper_mode_fill_fb_struct() can be used to pre-fill the required 51 * drm_helper_mode_fill_fb_struct() can be used to pre-fill the required
@@ -55,11 +55,11 @@
55 * drivers can grab additional references with drm_framebuffer_reference() and 55 * drivers can grab additional references with drm_framebuffer_reference() and
56 * drop them again with drm_framebuffer_unreference(). For driver-private 56 * drop them again with drm_framebuffer_unreference(). For driver-private
57 * framebuffers for which the last reference is never dropped (e.g. for the 57 * framebuffers for which the last reference is never dropped (e.g. for the
58 * fbdev framebuffer when the struct struct &drm_framebuffer is embedded into 58 * fbdev framebuffer when the struct &struct drm_framebuffer is embedded into
59 * the fbdev helper struct) drivers can manually clean up a framebuffer at 59 * the fbdev helper struct) drivers can manually clean up a framebuffer at
60 * module unload time with drm_framebuffer_unregister_private(). But doing this 60 * module unload time with drm_framebuffer_unregister_private(). But doing this
61 * is not recommended, and it's better to have a normal free-standing struct 61 * is not recommended, and it's better to have a normal free-standing &struct
62 * &drm_framebuffer. 62 * drm_framebuffer.
63 */ 63 */
64 64
65int drm_framebuffer_check_src_coords(uint32_t src_x, uint32_t src_y, 65int drm_framebuffer_check_src_coords(uint32_t src_x, uint32_t src_y,
@@ -126,111 +126,34 @@ int drm_mode_addfb(struct drm_device *dev,
126 return 0; 126 return 0;
127} 127}
128 128
129static int format_check(const struct drm_mode_fb_cmd2 *r)
130{
131 uint32_t format = r->pixel_format & ~DRM_FORMAT_BIG_ENDIAN;
132 char *format_name;
133
134 switch (format) {
135 case DRM_FORMAT_C8:
136 case DRM_FORMAT_RGB332:
137 case DRM_FORMAT_BGR233:
138 case DRM_FORMAT_XRGB4444:
139 case DRM_FORMAT_XBGR4444:
140 case DRM_FORMAT_RGBX4444:
141 case DRM_FORMAT_BGRX4444:
142 case DRM_FORMAT_ARGB4444:
143 case DRM_FORMAT_ABGR4444:
144 case DRM_FORMAT_RGBA4444:
145 case DRM_FORMAT_BGRA4444:
146 case DRM_FORMAT_XRGB1555:
147 case DRM_FORMAT_XBGR1555:
148 case DRM_FORMAT_RGBX5551:
149 case DRM_FORMAT_BGRX5551:
150 case DRM_FORMAT_ARGB1555:
151 case DRM_FORMAT_ABGR1555:
152 case DRM_FORMAT_RGBA5551:
153 case DRM_FORMAT_BGRA5551:
154 case DRM_FORMAT_RGB565:
155 case DRM_FORMAT_BGR565:
156 case DRM_FORMAT_RGB888:
157 case DRM_FORMAT_BGR888:
158 case DRM_FORMAT_XRGB8888:
159 case DRM_FORMAT_XBGR8888:
160 case DRM_FORMAT_RGBX8888:
161 case DRM_FORMAT_BGRX8888:
162 case DRM_FORMAT_ARGB8888:
163 case DRM_FORMAT_ABGR8888:
164 case DRM_FORMAT_RGBA8888:
165 case DRM_FORMAT_BGRA8888:
166 case DRM_FORMAT_XRGB2101010:
167 case DRM_FORMAT_XBGR2101010:
168 case DRM_FORMAT_RGBX1010102:
169 case DRM_FORMAT_BGRX1010102:
170 case DRM_FORMAT_ARGB2101010:
171 case DRM_FORMAT_ABGR2101010:
172 case DRM_FORMAT_RGBA1010102:
173 case DRM_FORMAT_BGRA1010102:
174 case DRM_FORMAT_YUYV:
175 case DRM_FORMAT_YVYU:
176 case DRM_FORMAT_UYVY:
177 case DRM_FORMAT_VYUY:
178 case DRM_FORMAT_AYUV:
179 case DRM_FORMAT_NV12:
180 case DRM_FORMAT_NV21:
181 case DRM_FORMAT_NV16:
182 case DRM_FORMAT_NV61:
183 case DRM_FORMAT_NV24:
184 case DRM_FORMAT_NV42:
185 case DRM_FORMAT_YUV410:
186 case DRM_FORMAT_YVU410:
187 case DRM_FORMAT_YUV411:
188 case DRM_FORMAT_YVU411:
189 case DRM_FORMAT_YUV420:
190 case DRM_FORMAT_YVU420:
191 case DRM_FORMAT_YUV422:
192 case DRM_FORMAT_YVU422:
193 case DRM_FORMAT_YUV444:
194 case DRM_FORMAT_YVU444:
195 return 0;
196 default:
197 format_name = drm_get_format_name(r->pixel_format);
198 DRM_DEBUG_KMS("invalid pixel format %s\n", format_name);
199 kfree(format_name);
200 return -EINVAL;
201 }
202}
203
204static int framebuffer_check(const struct drm_mode_fb_cmd2 *r) 129static int framebuffer_check(const struct drm_mode_fb_cmd2 *r)
205{ 130{
206 int ret, hsub, vsub, num_planes, i; 131 const struct drm_format_info *info;
207 132 int i;
208 ret = format_check(r); 133
209 if (ret) { 134 info = __drm_format_info(r->pixel_format & ~DRM_FORMAT_BIG_ENDIAN);
210 char *format_name = drm_get_format_name(r->pixel_format); 135 if (!info) {
211 DRM_DEBUG_KMS("bad framebuffer format %s\n", format_name); 136 struct drm_format_name_buf format_name;
212 kfree(format_name); 137 DRM_DEBUG_KMS("bad framebuffer format %s\n",
213 return ret; 138 drm_get_format_name(r->pixel_format,
139 &format_name));
140 return -EINVAL;
214 } 141 }
215 142
216 hsub = drm_format_horz_chroma_subsampling(r->pixel_format); 143 if (r->width == 0 || r->width % info->hsub) {
217 vsub = drm_format_vert_chroma_subsampling(r->pixel_format);
218 num_planes = drm_format_num_planes(r->pixel_format);
219
220 if (r->width == 0 || r->width % hsub) {
221 DRM_DEBUG_KMS("bad framebuffer width %u\n", r->width); 144 DRM_DEBUG_KMS("bad framebuffer width %u\n", r->width);
222 return -EINVAL; 145 return -EINVAL;
223 } 146 }
224 147
225 if (r->height == 0 || r->height % vsub) { 148 if (r->height == 0 || r->height % info->vsub) {
226 DRM_DEBUG_KMS("bad framebuffer height %u\n", r->height); 149 DRM_DEBUG_KMS("bad framebuffer height %u\n", r->height);
227 return -EINVAL; 150 return -EINVAL;
228 } 151 }
229 152
230 for (i = 0; i < num_planes; i++) { 153 for (i = 0; i < info->num_planes; i++) {
231 unsigned int width = r->width / (i != 0 ? hsub : 1); 154 unsigned int width = r->width / (i != 0 ? info->hsub : 1);
232 unsigned int height = r->height / (i != 0 ? vsub : 1); 155 unsigned int height = r->height / (i != 0 ? info->vsub : 1);
233 unsigned int cpp = drm_format_plane_cpp(r->pixel_format, i); 156 unsigned int cpp = info->cpp[i];
234 157
235 if (!r->handles[i]) { 158 if (!r->handles[i]) {
236 DRM_DEBUG_KMS("no buffer object handle for plane %d\n", i); 159 DRM_DEBUG_KMS("no buffer object handle for plane %d\n", i);
@@ -254,6 +177,13 @@ static int framebuffer_check(const struct drm_mode_fb_cmd2 *r)
254 return -EINVAL; 177 return -EINVAL;
255 } 178 }
256 179
180 if (r->flags & DRM_MODE_FB_MODIFIERS &&
181 r->modifier[i] != r->modifier[0]) {
182 DRM_DEBUG_KMS("bad fb modifier %llu for plane %d\n",
183 r->modifier[i], i);
184 return -EINVAL;
185 }
186
257 /* modifier specific checks: */ 187 /* modifier specific checks: */
258 switch (r->modifier[i]) { 188 switch (r->modifier[i]) {
259 case DRM_FORMAT_MOD_SAMSUNG_64_32_TILE: 189 case DRM_FORMAT_MOD_SAMSUNG_64_32_TILE:
@@ -273,7 +203,7 @@ static int framebuffer_check(const struct drm_mode_fb_cmd2 *r)
273 } 203 }
274 } 204 }
275 205
276 for (i = num_planes; i < 4; i++) { 206 for (i = info->num_planes; i < 4; i++) {
277 if (r->modifier[i]) { 207 if (r->modifier[i]) {
278 DRM_DEBUG_KMS("non-zero modifier for unused plane %d\n", i); 208 DRM_DEBUG_KMS("non-zero modifier for unused plane %d\n", i);
279 return -EINVAL; 209 return -EINVAL;
@@ -502,8 +432,8 @@ int drm_mode_getfb(struct drm_device *dev,
502 432
503 r->height = fb->height; 433 r->height = fb->height;
504 r->width = fb->width; 434 r->width = fb->width;
505 r->depth = fb->depth; 435 r->depth = fb->format->depth;
506 r->bpp = fb->bits_per_pixel; 436 r->bpp = fb->format->cpp[0] * 8;
507 r->pitch = fb->pitches[0]; 437 r->pitch = fb->pitches[0];
508 if (fb->funcs->create_handle) { 438 if (fb->funcs->create_handle) {
509 if (drm_is_current_master(file_priv) || capable(CAP_SYS_ADMIN) || 439 if (drm_is_current_master(file_priv) || capable(CAP_SYS_ADMIN) ||
@@ -540,7 +470,7 @@ int drm_mode_getfb(struct drm_device *dev,
540 * usb display-link, mipi manual update panels or edp panel self refresh modes. 470 * usb display-link, mipi manual update panels or edp panel self refresh modes.
541 * 471 *
542 * Modesetting drivers which always update the frontbuffer do not need to 472 * Modesetting drivers which always update the frontbuffer do not need to
543 * implement the corresponding ->dirty framebuffer callback. 473 * implement the corresponding &drm_framebuffer_funcs.dirty callback.
544 * 474 *
545 * Called by the user via ioctl. 475 * Called by the user via ioctl.
546 * 476 *
@@ -701,8 +631,11 @@ int drm_framebuffer_init(struct drm_device *dev, struct drm_framebuffer *fb,
701{ 631{
702 int ret; 632 int ret;
703 633
634 if (WARN_ON_ONCE(fb->dev != dev || !fb->format))
635 return -EINVAL;
636
704 INIT_LIST_HEAD(&fb->filp_head); 637 INIT_LIST_HEAD(&fb->filp_head);
705 fb->dev = dev; 638
706 fb->funcs = funcs; 639 fb->funcs = funcs;
707 640
708 ret = drm_mode_object_get_reg(dev, &fb->base, DRM_MODE_OBJECT_FB, 641 ret = drm_mode_object_get_reg(dev, &fb->base, DRM_MODE_OBJECT_FB,
@@ -751,6 +684,11 @@ EXPORT_SYMBOL(drm_framebuffer_lookup);
751 * those used for fbdev. Note that the caller must hold a reference of it's own, 684 * those used for fbdev. Note that the caller must hold a reference of it's own,
752 * i.e. the object may not be destroyed through this call (since it'll lead to a 685 * i.e. the object may not be destroyed through this call (since it'll lead to a
753 * locking inversion). 686 * locking inversion).
687 *
688 * NOTE: This function is deprecated. For driver-private framebuffers it is not
689 * recommended to embed a framebuffer struct info fbdev struct, instead, a
690 * framebuffer pointer is preferred and drm_framebuffer_unreference() should be
691 * called when the framebuffer is to be cleaned up.
754 */ 692 */
755void drm_framebuffer_unregister_private(struct drm_framebuffer *fb) 693void drm_framebuffer_unregister_private(struct drm_framebuffer *fb)
756{ 694{
@@ -771,10 +709,10 @@ EXPORT_SYMBOL(drm_framebuffer_unregister_private);
771 * @fb: framebuffer to remove 709 * @fb: framebuffer to remove
772 * 710 *
773 * Cleanup framebuffer. This function is intended to be used from the drivers 711 * Cleanup framebuffer. This function is intended to be used from the drivers
774 * ->destroy callback. It can also be used to clean up driver private 712 * &drm_framebuffer_funcs.destroy callback. It can also be used to clean up
775 * framebuffers embedded into a larger structure. 713 * driver private framebuffers embedded into a larger structure.
776 * 714 *
777 * Note that this function does not remove the fb from active usuage - if it is 715 * Note that this function does not remove the fb from active usage - if it is
778 * still used anywhere, hilarity can ensue since userspace could call getfb on 716 * still used anywhere, hilarity can ensue since userspace could call getfb on
779 * the id and get back -EINVAL. Obviously no concern at driver unload time. 717 * the id and get back -EINVAL. Obviously no concern at driver unload time.
780 * 718 *
@@ -855,3 +793,47 @@ void drm_framebuffer_remove(struct drm_framebuffer *fb)
855 drm_framebuffer_unreference(fb); 793 drm_framebuffer_unreference(fb);
856} 794}
857EXPORT_SYMBOL(drm_framebuffer_remove); 795EXPORT_SYMBOL(drm_framebuffer_remove);
796
797/**
798 * drm_framebuffer_plane_width - width of the plane given the first plane
799 * @width: width of the first plane
800 * @fb: the framebuffer
801 * @plane: plane index
802 *
803 * Returns:
804 * The width of @plane, given that the width of the first plane is @width.
805 */
806int drm_framebuffer_plane_width(int width,
807 const struct drm_framebuffer *fb, int plane)
808{
809 if (plane >= fb->format->num_planes)
810 return 0;
811
812 if (plane == 0)
813 return width;
814
815 return width / fb->format->hsub;
816}
817EXPORT_SYMBOL(drm_framebuffer_plane_width);
818
819/**
820 * drm_framebuffer_plane_height - height of the plane given the first plane
821 * @height: height of the first plane
822 * @fb: the framebuffer
823 * @plane: plane index
824 *
825 * Returns:
826 * The height of @plane, given that the height of the first plane is @height.
827 */
828int drm_framebuffer_plane_height(int height,
829 const struct drm_framebuffer *fb, int plane)
830{
831 if (plane >= fb->format->num_planes)
832 return 0;
833
834 if (plane == 0)
835 return height;
836
837 return height / fb->format->vsub;
838}
839EXPORT_SYMBOL(drm_framebuffer_plane_height);