]> asedeno.scripts.mit.edu Git - linux.git/blob - include/drm/drm_fb_helper.h
Merge tag 'spi-fix-v5.5-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi
[linux.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  * @dirty_clip: clip rectangle used with deferred_io to accumulate damage to
104  *              the screen buffer
105  * @dirty_lock: spinlock protecting @dirty_clip
106  * @dirty_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 dirty_clip;
135         spinlock_t dirty_lock;
136         struct work_struct dirty_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,
217                        struct drm_fb_helper *helper, int max_conn);
218 void drm_fb_helper_fini(struct drm_fb_helper *helper);
219 int drm_fb_helper_blank(int blank, struct fb_info *info);
220 int drm_fb_helper_pan_display(struct fb_var_screeninfo *var,
221                               struct fb_info *info);
222 int drm_fb_helper_set_par(struct fb_info *info);
223 int drm_fb_helper_check_var(struct fb_var_screeninfo *var,
224                             struct fb_info *info);
225
226 int drm_fb_helper_restore_fbdev_mode_unlocked(struct drm_fb_helper *fb_helper);
227
228 struct fb_info *drm_fb_helper_alloc_fbi(struct drm_fb_helper *fb_helper);
229 void drm_fb_helper_unregister_fbi(struct drm_fb_helper *fb_helper);
230 void drm_fb_helper_fill_info(struct fb_info *info,
231                              struct drm_fb_helper *fb_helper,
232                              struct drm_fb_helper_surface_size *sizes);
233
234 void drm_fb_helper_unlink_fbi(struct drm_fb_helper *fb_helper);
235
236 void drm_fb_helper_deferred_io(struct fb_info *info,
237                                struct list_head *pagelist);
238
239 ssize_t drm_fb_helper_sys_read(struct fb_info *info, char __user *buf,
240                                size_t count, loff_t *ppos);
241 ssize_t drm_fb_helper_sys_write(struct fb_info *info, const char __user *buf,
242                                 size_t count, loff_t *ppos);
243
244 void drm_fb_helper_sys_fillrect(struct fb_info *info,
245                                 const struct fb_fillrect *rect);
246 void drm_fb_helper_sys_copyarea(struct fb_info *info,
247                                 const struct fb_copyarea *area);
248 void drm_fb_helper_sys_imageblit(struct fb_info *info,
249                                  const struct fb_image *image);
250
251 void drm_fb_helper_cfb_fillrect(struct fb_info *info,
252                                 const struct fb_fillrect *rect);
253 void drm_fb_helper_cfb_copyarea(struct fb_info *info,
254                                 const struct fb_copyarea *area);
255 void drm_fb_helper_cfb_imageblit(struct fb_info *info,
256                                  const struct fb_image *image);
257
258 void drm_fb_helper_set_suspend(struct drm_fb_helper *fb_helper, bool suspend);
259 void drm_fb_helper_set_suspend_unlocked(struct drm_fb_helper *fb_helper,
260                                         bool suspend);
261
262 int drm_fb_helper_setcmap(struct fb_cmap *cmap, struct fb_info *info);
263
264 int drm_fb_helper_ioctl(struct fb_info *info, unsigned int cmd,
265                         unsigned long arg);
266
267 int drm_fb_helper_hotplug_event(struct drm_fb_helper *fb_helper);
268 int drm_fb_helper_initial_config(struct drm_fb_helper *fb_helper, int bpp_sel);
269 int drm_fb_helper_debug_enter(struct fb_info *info);
270 int drm_fb_helper_debug_leave(struct fb_info *info);
271
272 int drm_fb_helper_fbdev_setup(struct drm_device *dev,
273                               struct drm_fb_helper *fb_helper,
274                               const struct drm_fb_helper_funcs *funcs,
275                               unsigned int preferred_bpp,
276                               unsigned int max_conn_count);
277 void drm_fb_helper_fbdev_teardown(struct drm_device *dev);
278
279 void drm_fb_helper_lastclose(struct drm_device *dev);
280 void drm_fb_helper_output_poll_changed(struct drm_device *dev);
281
282 int drm_fb_helper_generic_probe(struct drm_fb_helper *fb_helper,
283                                 struct drm_fb_helper_surface_size *sizes);
284 int drm_fbdev_generic_setup(struct drm_device *dev, unsigned int preferred_bpp);
285 #else
286 static inline void drm_fb_helper_prepare(struct drm_device *dev,
287                                         struct drm_fb_helper *helper,
288                                         const struct drm_fb_helper_funcs *funcs)
289 {
290 }
291
292 static inline int drm_fb_helper_init(struct drm_device *dev,
293                        struct drm_fb_helper *helper,
294                        int max_conn)
295 {
296         /* So drivers can use it to free the struct */
297         helper->dev = dev;
298         dev->fb_helper = helper;
299
300         return 0;
301 }
302
303 static inline void drm_fb_helper_fini(struct drm_fb_helper *helper)
304 {
305         if (helper && helper->dev)
306                 helper->dev->fb_helper = NULL;
307 }
308
309 static inline int drm_fb_helper_blank(int blank, struct fb_info *info)
310 {
311         return 0;
312 }
313
314 static inline int drm_fb_helper_pan_display(struct fb_var_screeninfo *var,
315                                             struct fb_info *info)
316 {
317         return 0;
318 }
319
320 static inline int drm_fb_helper_set_par(struct fb_info *info)
321 {
322         return 0;
323 }
324
325 static inline int drm_fb_helper_check_var(struct fb_var_screeninfo *var,
326                                           struct fb_info *info)
327 {
328         return 0;
329 }
330
331 static inline int
332 drm_fb_helper_restore_fbdev_mode_unlocked(struct drm_fb_helper *fb_helper)
333 {
334         return 0;
335 }
336
337 static inline struct fb_info *
338 drm_fb_helper_alloc_fbi(struct drm_fb_helper *fb_helper)
339 {
340         return NULL;
341 }
342
343 static inline void drm_fb_helper_unregister_fbi(struct drm_fb_helper *fb_helper)
344 {
345 }
346
347 static inline void
348 drm_fb_helper_fill_info(struct fb_info *info,
349                         struct drm_fb_helper *fb_helper,
350                         struct drm_fb_helper_surface_size *sizes)
351 {
352 }
353
354 static inline int drm_fb_helper_setcmap(struct fb_cmap *cmap,
355                                         struct fb_info *info)
356 {
357         return 0;
358 }
359
360 static inline int drm_fb_helper_ioctl(struct fb_info *info, unsigned int cmd,
361                                       unsigned long arg)
362 {
363         return 0;
364 }
365
366 static inline void drm_fb_helper_unlink_fbi(struct drm_fb_helper *fb_helper)
367 {
368 }
369
370 static inline void drm_fb_helper_deferred_io(struct fb_info *info,
371                                              struct list_head *pagelist)
372 {
373 }
374
375 static inline int drm_fb_helper_defio_init(struct drm_fb_helper *fb_helper)
376 {
377         return -ENODEV;
378 }
379
380 static inline ssize_t drm_fb_helper_sys_read(struct fb_info *info,
381                                              char __user *buf, size_t count,
382                                              loff_t *ppos)
383 {
384         return -ENODEV;
385 }
386
387 static inline ssize_t drm_fb_helper_sys_write(struct fb_info *info,
388                                               const char __user *buf,
389                                               size_t count, loff_t *ppos)
390 {
391         return -ENODEV;
392 }
393
394 static inline void drm_fb_helper_sys_fillrect(struct fb_info *info,
395                                               const struct fb_fillrect *rect)
396 {
397 }
398
399 static inline void drm_fb_helper_sys_copyarea(struct fb_info *info,
400                                               const struct fb_copyarea *area)
401 {
402 }
403
404 static inline void drm_fb_helper_sys_imageblit(struct fb_info *info,
405                                                const struct fb_image *image)
406 {
407 }
408
409 static inline void drm_fb_helper_cfb_fillrect(struct fb_info *info,
410                                               const struct fb_fillrect *rect)
411 {
412 }
413
414 static inline void drm_fb_helper_cfb_copyarea(struct fb_info *info,
415                                               const struct fb_copyarea *area)
416 {
417 }
418
419 static inline void drm_fb_helper_cfb_imageblit(struct fb_info *info,
420                                                const struct fb_image *image)
421 {
422 }
423
424 static inline void drm_fb_helper_set_suspend(struct drm_fb_helper *fb_helper,
425                                              bool suspend)
426 {
427 }
428
429 static inline void
430 drm_fb_helper_set_suspend_unlocked(struct drm_fb_helper *fb_helper, bool suspend)
431 {
432 }
433
434 static inline int drm_fb_helper_hotplug_event(struct drm_fb_helper *fb_helper)
435 {
436         return 0;
437 }
438
439 static inline int drm_fb_helper_initial_config(struct drm_fb_helper *fb_helper,
440                                                int bpp_sel)
441 {
442         return 0;
443 }
444
445 static inline int drm_fb_helper_debug_enter(struct fb_info *info)
446 {
447         return 0;
448 }
449
450 static inline int drm_fb_helper_debug_leave(struct fb_info *info)
451 {
452         return 0;
453 }
454
455 static inline int
456 drm_fb_helper_fbdev_setup(struct drm_device *dev,
457                           struct drm_fb_helper *fb_helper,
458                           const struct drm_fb_helper_funcs *funcs,
459                           unsigned int preferred_bpp,
460                           unsigned int max_conn_count)
461 {
462         /* So drivers can use it to free the struct */
463         dev->fb_helper = fb_helper;
464
465         return 0;
466 }
467
468 static inline void drm_fb_helper_fbdev_teardown(struct drm_device *dev)
469 {
470         dev->fb_helper = NULL;
471 }
472
473 static inline void drm_fb_helper_lastclose(struct drm_device *dev)
474 {
475 }
476
477 static inline void drm_fb_helper_output_poll_changed(struct drm_device *dev)
478 {
479 }
480
481 static inline int
482 drm_fb_helper_generic_probe(struct drm_fb_helper *fb_helper,
483                             struct drm_fb_helper_surface_size *sizes)
484 {
485         return 0;
486 }
487
488 static inline int
489 drm_fbdev_generic_setup(struct drm_device *dev, unsigned int preferred_bpp)
490 {
491         return 0;
492 }
493
494 #endif
495
496 /* TODO: There's a todo entry to remove these three */
497 static inline int
498 drm_fb_helper_single_add_all_connectors(struct drm_fb_helper *fb_helper)
499 {
500         return 0;
501 }
502
503 static inline int
504 drm_fb_helper_add_one_connector(struct drm_fb_helper *fb_helper,
505                                 struct drm_connector *connector)
506 {
507         return 0;
508 }
509
510 static inline int
511 drm_fb_helper_remove_one_connector(struct drm_fb_helper *fb_helper,
512                                    struct drm_connector *connector)
513 {
514         return 0;
515 }
516
517 /**
518  * drm_fb_helper_remove_conflicting_framebuffers - remove firmware-configured framebuffers
519  * @a: memory range, users of which are to be removed
520  * @name: requesting driver name
521  * @primary: also kick vga16fb if present
522  *
523  * This function removes framebuffer devices (initialized by firmware/bootloader)
524  * which use memory range described by @a. If @a is NULL all such devices are
525  * removed.
526  */
527 static inline int
528 drm_fb_helper_remove_conflicting_framebuffers(struct apertures_struct *a,
529                                               const char *name, bool primary)
530 {
531 #if IS_REACHABLE(CONFIG_FB)
532         return remove_conflicting_framebuffers(a, name, primary);
533 #else
534         return 0;
535 #endif
536 }
537
538 /**
539  * drm_fb_helper_remove_conflicting_pci_framebuffers - remove firmware-configured framebuffers for PCI devices
540  * @pdev: PCI device
541  * @name: requesting driver name
542  *
543  * This function removes framebuffer devices (eg. initialized by firmware)
544  * using memory range configured for any of @pdev's memory bars.
545  *
546  * The function assumes that PCI device with shadowed ROM drives a primary
547  * display and so kicks out vga16fb.
548  */
549 static inline int
550 drm_fb_helper_remove_conflicting_pci_framebuffers(struct pci_dev *pdev,
551                                                   const char *name)
552 {
553         int ret = 0;
554
555         /*
556          * WARNING: Apparently we must kick fbdev drivers before vgacon,
557          * otherwise the vga fbdev driver falls over.
558          */
559 #if IS_REACHABLE(CONFIG_FB)
560         ret = remove_conflicting_pci_framebuffers(pdev, name);
561 #endif
562         if (ret == 0)
563                 ret = vga_remove_vgacon(pdev);
564         return ret;
565 }
566
567 #endif