tools headers UAPI: Sync openat2.h with the kernel sources
[linux-2.6-microblaze.git] / include / drm / drm_fb_helper.h
1 /*
2  * Copyright (c) 2006-2009 Red Hat Inc.
3  * Copyright (c) 2006-2008 Intel Corporation
4  * Copyright (c) 2007 Dave Airlie <airlied@linux.ie>
5  *
6  * DRM framebuffer helper functions
7  *
8  * Permission to use, copy, modify, distribute, and sell this software and its
9  * documentation for any purpose is hereby granted without fee, provided that
10  * the above copyright notice appear in all copies and that both that copyright
11  * notice and this permission notice appear in supporting documentation, and
12  * that the name of the copyright holders not be used in advertising or
13  * publicity pertaining to distribution of the software without specific,
14  * written prior permission.  The copyright holders make no representations
15  * about the suitability of this software for any purpose.  It is provided "as
16  * is" without express or implied warranty.
17  *
18  * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
19  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
20  * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
21  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
22  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
23  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
24  * OF THIS SOFTWARE.
25  *
26  * Authors:
27  *      Dave Airlie <airlied@linux.ie>
28  *      Jesse Barnes <jesse.barnes@intel.com>
29  */
30 #ifndef DRM_FB_HELPER_H
31 #define DRM_FB_HELPER_H
32
33 struct drm_fb_helper;
34
35 #include <drm/drm_client.h>
36 #include <drm/drm_crtc.h>
37 #include <drm/drm_device.h>
38 #include <linux/kgdb.h>
39 #include <linux/vgaarb.h>
40
41 enum mode_set_atomic {
42         LEAVE_ATOMIC_MODE_SET,
43         ENTER_ATOMIC_MODE_SET,
44 };
45
46 /**
47  * struct drm_fb_helper_surface_size - describes fbdev size and scanout surface size
48  * @fb_width: fbdev width
49  * @fb_height: fbdev height
50  * @surface_width: scanout buffer width
51  * @surface_height: scanout buffer height
52  * @surface_bpp: scanout buffer bpp
53  * @surface_depth: scanout buffer depth
54  *
55  * Note that the scanout surface width/height may be larger than the fbdev
56  * width/height.  In case of multiple displays, the scanout surface is sized
57  * according to the largest width/height (so it is large enough for all CRTCs
58  * to scanout).  But the fbdev width/height is sized to the minimum width/
59  * height of all the displays.  This ensures that fbcon fits on the smallest
60  * of the attached displays. fb_width/fb_height is used by
61  * drm_fb_helper_fill_info() to fill out the &fb_info.var structure.
62  */
63 struct drm_fb_helper_surface_size {
64         u32 fb_width;
65         u32 fb_height;
66         u32 surface_width;
67         u32 surface_height;
68         u32 surface_bpp;
69         u32 surface_depth;
70 };
71
72 /**
73  * struct drm_fb_helper_funcs - driver callbacks for the fbdev emulation library
74  *
75  * Driver callbacks used by the fbdev emulation helper library.
76  */
77 struct drm_fb_helper_funcs {
78         /**
79          * @fb_probe:
80          *
81          * Driver callback to allocate and initialize the fbdev info structure.
82          * Furthermore it also needs to allocate the DRM framebuffer used to
83          * back the fbdev.
84          *
85          * This callback is mandatory.
86          *
87          * RETURNS:
88          *
89          * The driver should return 0 on success and a negative error code on
90          * failure.
91          */
92         int (*fb_probe)(struct drm_fb_helper *helper,
93                         struct drm_fb_helper_surface_size *sizes);
94 };
95
96 /**
97  * struct drm_fb_helper - main structure to emulate fbdev on top of KMS
98  * @fb: Scanout framebuffer object
99  * @dev: DRM device
100  * @funcs: driver callbacks for fb helper
101  * @fbdev: emulated fbdev device info struct
102  * @pseudo_palette: fake palette of 16 colors
103  * @damage_clip: clip rectangle used with deferred_io to accumulate damage to
104  *                the screen buffer
105  * @damage_lock: spinlock protecting @damage_clip
106  * @damage_work: worker used to flush the framebuffer
107  * @resume_work: worker used during resume if the console lock is already taken
108  *
109  * This is the main structure used by the fbdev helpers. Drivers supporting
110  * fbdev emulation should embedded this into their overall driver structure.
111  * Drivers must also fill out a &struct drm_fb_helper_funcs with a few
112  * operations.
113  */
114 struct drm_fb_helper {
115         /**
116          * @client:
117          *
118          * DRM client used by the generic fbdev emulation.
119          */
120         struct drm_client_dev client;
121
122         /**
123          * @buffer:
124          *
125          * Framebuffer used by the generic fbdev emulation.
126          */
127         struct drm_client_buffer *buffer;
128
129         struct drm_framebuffer *fb;
130         struct drm_device *dev;
131         const struct drm_fb_helper_funcs *funcs;
132         struct fb_info *fbdev;
133         u32 pseudo_palette[17];
134         struct drm_clip_rect damage_clip;
135         spinlock_t damage_lock;
136         struct work_struct damage_work;
137         struct work_struct resume_work;
138
139         /**
140          * @lock:
141          *
142          * Top-level FBDEV helper lock. This protects all internal data
143          * structures and lists, such as @connector_info and @crtc_info.
144          *
145          * FIXME: fbdev emulation locking is a mess and long term we want to
146          * protect all helper internal state with this lock as well as reduce
147          * core KMS locking as much as possible.
148          */
149         struct mutex lock;
150
151         /**
152          * @kernel_fb_list:
153          *
154          * Entry on the global kernel_fb_helper_list, used for kgdb entry/exit.
155          */
156         struct list_head kernel_fb_list;
157
158         /**
159          * @delayed_hotplug:
160          *
161          * A hotplug was received while fbdev wasn't in control of the DRM
162          * device, i.e. another KMS master was active. The output configuration
163          * needs to be reprobe when fbdev is in control again.
164          */
165         bool delayed_hotplug;
166
167         /**
168          * @deferred_setup:
169          *
170          * If no outputs are connected (disconnected or unknown) the FB helper
171          * code will defer setup until at least one of the outputs shows up.
172          * This field keeps track of the status so that setup can be retried
173          * at every hotplug event until it succeeds eventually.
174          *
175          * Protected by @lock.
176          */
177         bool deferred_setup;
178
179         /**
180          * @preferred_bpp:
181          *
182          * Temporary storage for the driver's preferred BPP setting passed to
183          * FB helper initialization. This needs to be tracked so that deferred
184          * FB helper setup can pass this on.
185          *
186          * See also: @deferred_setup
187          */
188         int preferred_bpp;
189 };
190
191 static inline struct drm_fb_helper *
192 drm_fb_helper_from_client(struct drm_client_dev *client)
193 {
194         return container_of(client, struct drm_fb_helper, client);
195 }
196
197 /**
198  * define DRM_FB_HELPER_DEFAULT_OPS - helper define for drm drivers
199  *
200  * Helper define to register default implementations of drm_fb_helper
201  * functions. To be used in struct fb_ops of drm drivers.
202  */
203 #define DRM_FB_HELPER_DEFAULT_OPS \
204         .fb_check_var   = drm_fb_helper_check_var, \
205         .fb_set_par     = drm_fb_helper_set_par, \
206         .fb_setcmap     = drm_fb_helper_setcmap, \
207         .fb_blank       = drm_fb_helper_blank, \
208         .fb_pan_display = drm_fb_helper_pan_display, \
209         .fb_debug_enter = drm_fb_helper_debug_enter, \
210         .fb_debug_leave = drm_fb_helper_debug_leave, \
211         .fb_ioctl       = drm_fb_helper_ioctl
212
213 #ifdef CONFIG_DRM_FBDEV_EMULATION
214 void drm_fb_helper_prepare(struct drm_device *dev, struct drm_fb_helper *helper,
215                            const struct drm_fb_helper_funcs *funcs);
216 int drm_fb_helper_init(struct drm_device *dev, struct drm_fb_helper *helper);
217 void drm_fb_helper_fini(struct drm_fb_helper *helper);
218 int drm_fb_helper_blank(int blank, struct fb_info *info);
219 int drm_fb_helper_pan_display(struct fb_var_screeninfo *var,
220                               struct fb_info *info);
221 int drm_fb_helper_set_par(struct fb_info *info);
222 int drm_fb_helper_check_var(struct fb_var_screeninfo *var,
223                             struct fb_info *info);
224
225 int drm_fb_helper_restore_fbdev_mode_unlocked(struct drm_fb_helper *fb_helper);
226
227 struct fb_info *drm_fb_helper_alloc_fbi(struct drm_fb_helper *fb_helper);
228 void drm_fb_helper_unregister_fbi(struct drm_fb_helper *fb_helper);
229 void drm_fb_helper_fill_info(struct fb_info *info,
230                              struct drm_fb_helper *fb_helper,
231                              struct drm_fb_helper_surface_size *sizes);
232
233 void drm_fb_helper_deferred_io(struct fb_info *info,
234                                struct list_head *pagelist);
235
236 ssize_t drm_fb_helper_sys_read(struct fb_info *info, char __user *buf,
237                                size_t count, loff_t *ppos);
238 ssize_t drm_fb_helper_sys_write(struct fb_info *info, const char __user *buf,
239                                 size_t count, loff_t *ppos);
240
241 void drm_fb_helper_sys_fillrect(struct fb_info *info,
242                                 const struct fb_fillrect *rect);
243 void drm_fb_helper_sys_copyarea(struct fb_info *info,
244                                 const struct fb_copyarea *area);
245 void drm_fb_helper_sys_imageblit(struct fb_info *info,
246                                  const struct fb_image *image);
247
248 void drm_fb_helper_cfb_fillrect(struct fb_info *info,
249                                 const struct fb_fillrect *rect);
250 void drm_fb_helper_cfb_copyarea(struct fb_info *info,
251                                 const struct fb_copyarea *area);
252 void drm_fb_helper_cfb_imageblit(struct fb_info *info,
253                                  const struct fb_image *image);
254
255 void drm_fb_helper_set_suspend(struct drm_fb_helper *fb_helper, bool suspend);
256 void drm_fb_helper_set_suspend_unlocked(struct drm_fb_helper *fb_helper,
257                                         bool suspend);
258
259 int drm_fb_helper_setcmap(struct fb_cmap *cmap, struct fb_info *info);
260
261 int drm_fb_helper_ioctl(struct fb_info *info, unsigned int cmd,
262                         unsigned long arg);
263
264 int drm_fb_helper_hotplug_event(struct drm_fb_helper *fb_helper);
265 int drm_fb_helper_initial_config(struct drm_fb_helper *fb_helper, int bpp_sel);
266 int drm_fb_helper_debug_enter(struct fb_info *info);
267 int drm_fb_helper_debug_leave(struct fb_info *info);
268
269 void drm_fb_helper_lastclose(struct drm_device *dev);
270 void drm_fb_helper_output_poll_changed(struct drm_device *dev);
271
272 void drm_fbdev_generic_setup(struct drm_device *dev,
273                              unsigned int preferred_bpp);
274 #else
275 static inline void drm_fb_helper_prepare(struct drm_device *dev,
276                                         struct drm_fb_helper *helper,
277                                         const struct drm_fb_helper_funcs *funcs)
278 {
279 }
280
281 static inline int drm_fb_helper_init(struct drm_device *dev,
282                        struct drm_fb_helper *helper)
283 {
284         /* So drivers can use it to free the struct */
285         helper->dev = dev;
286         dev->fb_helper = helper;
287
288         return 0;
289 }
290
291 static inline void drm_fb_helper_fini(struct drm_fb_helper *helper)
292 {
293         if (helper && helper->dev)
294                 helper->dev->fb_helper = NULL;
295 }
296
297 static inline int drm_fb_helper_blank(int blank, struct fb_info *info)
298 {
299         return 0;
300 }
301
302 static inline int drm_fb_helper_pan_display(struct fb_var_screeninfo *var,
303                                             struct fb_info *info)
304 {
305         return 0;
306 }
307
308 static inline int drm_fb_helper_set_par(struct fb_info *info)
309 {
310         return 0;
311 }
312
313 static inline int drm_fb_helper_check_var(struct fb_var_screeninfo *var,
314                                           struct fb_info *info)
315 {
316         return 0;
317 }
318
319 static inline int
320 drm_fb_helper_restore_fbdev_mode_unlocked(struct drm_fb_helper *fb_helper)
321 {
322         return 0;
323 }
324
325 static inline struct fb_info *
326 drm_fb_helper_alloc_fbi(struct drm_fb_helper *fb_helper)
327 {
328         return NULL;
329 }
330
331 static inline void drm_fb_helper_unregister_fbi(struct drm_fb_helper *fb_helper)
332 {
333 }
334
335 static inline void
336 drm_fb_helper_fill_info(struct fb_info *info,
337                         struct drm_fb_helper *fb_helper,
338                         struct drm_fb_helper_surface_size *sizes)
339 {
340 }
341
342 static inline int drm_fb_helper_setcmap(struct fb_cmap *cmap,
343                                         struct fb_info *info)
344 {
345         return 0;
346 }
347
348 static inline int drm_fb_helper_ioctl(struct fb_info *info, unsigned int cmd,
349                                       unsigned long arg)
350 {
351         return 0;
352 }
353
354 static inline void drm_fb_helper_deferred_io(struct fb_info *info,
355                                              struct list_head *pagelist)
356 {
357 }
358
359 static inline int drm_fb_helper_defio_init(struct drm_fb_helper *fb_helper)
360 {
361         return -ENODEV;
362 }
363
364 static inline ssize_t drm_fb_helper_sys_read(struct fb_info *info,
365                                              char __user *buf, size_t count,
366                                              loff_t *ppos)
367 {
368         return -ENODEV;
369 }
370
371 static inline ssize_t drm_fb_helper_sys_write(struct fb_info *info,
372                                               const char __user *buf,
373                                               size_t count, loff_t *ppos)
374 {
375         return -ENODEV;
376 }
377
378 static inline void drm_fb_helper_sys_fillrect(struct fb_info *info,
379                                               const struct fb_fillrect *rect)
380 {
381 }
382
383 static inline void drm_fb_helper_sys_copyarea(struct fb_info *info,
384                                               const struct fb_copyarea *area)
385 {
386 }
387
388 static inline void drm_fb_helper_sys_imageblit(struct fb_info *info,
389                                                const struct fb_image *image)
390 {
391 }
392
393 static inline void drm_fb_helper_cfb_fillrect(struct fb_info *info,
394                                               const struct fb_fillrect *rect)
395 {
396 }
397
398 static inline void drm_fb_helper_cfb_copyarea(struct fb_info *info,
399                                               const struct fb_copyarea *area)
400 {
401 }
402
403 static inline void drm_fb_helper_cfb_imageblit(struct fb_info *info,
404                                                const struct fb_image *image)
405 {
406 }
407
408 static inline void drm_fb_helper_set_suspend(struct drm_fb_helper *fb_helper,
409                                              bool suspend)
410 {
411 }
412
413 static inline void
414 drm_fb_helper_set_suspend_unlocked(struct drm_fb_helper *fb_helper, bool suspend)
415 {
416 }
417
418 static inline int drm_fb_helper_hotplug_event(struct drm_fb_helper *fb_helper)
419 {
420         return 0;
421 }
422
423 static inline int drm_fb_helper_initial_config(struct drm_fb_helper *fb_helper,
424                                                int bpp_sel)
425 {
426         return 0;
427 }
428
429 static inline int drm_fb_helper_debug_enter(struct fb_info *info)
430 {
431         return 0;
432 }
433
434 static inline int drm_fb_helper_debug_leave(struct fb_info *info)
435 {
436         return 0;
437 }
438
439 static inline void drm_fb_helper_lastclose(struct drm_device *dev)
440 {
441 }
442
443 static inline void drm_fb_helper_output_poll_changed(struct drm_device *dev)
444 {
445 }
446
447 static inline void
448 drm_fbdev_generic_setup(struct drm_device *dev, unsigned int preferred_bpp)
449 {
450 }
451
452 #endif
453
454 /**
455  * drm_fb_helper_remove_conflicting_framebuffers - remove firmware-configured framebuffers
456  * @a: memory range, users of which are to be removed
457  * @name: requesting driver name
458  * @primary: also kick vga16fb if present
459  *
460  * This function removes framebuffer devices (initialized by firmware/bootloader)
461  * which use memory range described by @a. If @a is NULL all such devices are
462  * removed.
463  */
464 static inline int
465 drm_fb_helper_remove_conflicting_framebuffers(struct apertures_struct *a,
466                                               const char *name, bool primary)
467 {
468 #if IS_REACHABLE(CONFIG_FB)
469         return remove_conflicting_framebuffers(a, name, primary);
470 #else
471         return 0;
472 #endif
473 }
474
475 /**
476  * drm_fb_helper_remove_conflicting_pci_framebuffers - remove firmware-configured framebuffers for PCI devices
477  * @pdev: PCI device
478  * @name: requesting driver name
479  *
480  * This function removes framebuffer devices (eg. initialized by firmware)
481  * using memory range configured for any of @pdev's memory bars.
482  *
483  * The function assumes that PCI device with shadowed ROM drives a primary
484  * display and so kicks out vga16fb.
485  */
486 static inline int
487 drm_fb_helper_remove_conflicting_pci_framebuffers(struct pci_dev *pdev,
488                                                   const char *name)
489 {
490         int ret = 0;
491
492         /*
493          * WARNING: Apparently we must kick fbdev drivers before vgacon,
494          * otherwise the vga fbdev driver falls over.
495          */
496 #if IS_REACHABLE(CONFIG_FB)
497         ret = remove_conflicting_pci_framebuffers(pdev, name);
498 #endif
499         if (ret == 0)
500                 ret = vga_remove_vgacon(pdev);
501         return ret;
502 }
503
504 #endif