]> git.ipfire.org Git - thirdparty/kernel/linux.git/blob - include/drm/drm_fb_helper.h
drm/fb-helper: Fixup fill_info cleanup
[thirdparty/kernel/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
40 enum mode_set_atomic {
41 LEAVE_ATOMIC_MODE_SET,
42 ENTER_ATOMIC_MODE_SET,
43 };
44
45 struct drm_fb_offset {
46 int x, y;
47 };
48
49 struct drm_fb_helper_crtc {
50 struct drm_mode_set mode_set;
51 struct drm_display_mode *desired_mode;
52 int x, y;
53 int rotation;
54 };
55
56 /**
57 * struct drm_fb_helper_surface_size - describes fbdev size and scanout surface size
58 * @fb_width: fbdev width
59 * @fb_height: fbdev height
60 * @surface_width: scanout buffer width
61 * @surface_height: scanout buffer height
62 * @surface_bpp: scanout buffer bpp
63 * @surface_depth: scanout buffer depth
64 *
65 * Note that the scanout surface width/height may be larger than the fbdev
66 * width/height. In case of multiple displays, the scanout surface is sized
67 * according to the largest width/height (so it is large enough for all CRTCs
68 * to scanout). But the fbdev width/height is sized to the minimum width/
69 * height of all the displays. This ensures that fbcon fits on the smallest
70 * of the attached displays. fb_width/fb_height is used by
71 * drm_fb_helper_fill_info() to fill out the &fb_info.var structure.
72 */
73 struct drm_fb_helper_surface_size {
74 u32 fb_width;
75 u32 fb_height;
76 u32 surface_width;
77 u32 surface_height;
78 u32 surface_bpp;
79 u32 surface_depth;
80 };
81
82 /**
83 * struct drm_fb_helper_funcs - driver callbacks for the fbdev emulation library
84 *
85 * Driver callbacks used by the fbdev emulation helper library.
86 */
87 struct drm_fb_helper_funcs {
88 /**
89 * @fb_probe:
90 *
91 * Driver callback to allocate and initialize the fbdev info structure.
92 * Furthermore it also needs to allocate the DRM framebuffer used to
93 * back the fbdev.
94 *
95 * This callback is mandatory.
96 *
97 * RETURNS:
98 *
99 * The driver should return 0 on success and a negative error code on
100 * failure.
101 */
102 int (*fb_probe)(struct drm_fb_helper *helper,
103 struct drm_fb_helper_surface_size *sizes);
104
105 /**
106 * @initial_config:
107 *
108 * Driver callback to setup an initial fbdev display configuration.
109 * Drivers can use this callback to tell the fbdev emulation what the
110 * preferred initial configuration is. This is useful to implement
111 * smooth booting where the fbdev (and subsequently all userspace) never
112 * changes the mode, but always inherits the existing configuration.
113 *
114 * This callback is optional.
115 *
116 * RETURNS:
117 *
118 * The driver should return true if a suitable initial configuration has
119 * been filled out and false when the fbdev helper should fall back to
120 * the default probing logic.
121 */
122 bool (*initial_config)(struct drm_fb_helper *fb_helper,
123 struct drm_fb_helper_crtc **crtcs,
124 struct drm_display_mode **modes,
125 struct drm_fb_offset *offsets,
126 bool *enabled, int width, int height);
127 };
128
129 struct drm_fb_helper_connector {
130 struct drm_connector *connector;
131 };
132
133 /**
134 * struct drm_fb_helper - main structure to emulate fbdev on top of KMS
135 * @fb: Scanout framebuffer object
136 * @dev: DRM device
137 * @crtc_count: number of possible CRTCs
138 * @crtc_info: per-CRTC helper state (mode, x/y offset, etc)
139 * @connector_count: number of connected connectors
140 * @connector_info_alloc_count: size of connector_info
141 * @funcs: driver callbacks for fb helper
142 * @fbdev: emulated fbdev device info struct
143 * @pseudo_palette: fake palette of 16 colors
144 * @dirty_clip: clip rectangle used with deferred_io to accumulate damage to
145 * the screen buffer
146 * @dirty_lock: spinlock protecting @dirty_clip
147 * @dirty_work: worker used to flush the framebuffer
148 * @resume_work: worker used during resume if the console lock is already taken
149 *
150 * This is the main structure used by the fbdev helpers. Drivers supporting
151 * fbdev emulation should embedded this into their overall driver structure.
152 * Drivers must also fill out a &struct drm_fb_helper_funcs with a few
153 * operations.
154 */
155 struct drm_fb_helper {
156 /**
157 * @client:
158 *
159 * DRM client used by the generic fbdev emulation.
160 */
161 struct drm_client_dev client;
162
163 /**
164 * @buffer:
165 *
166 * Framebuffer used by the generic fbdev emulation.
167 */
168 struct drm_client_buffer *buffer;
169
170 struct drm_framebuffer *fb;
171 struct drm_device *dev;
172 int crtc_count;
173 struct drm_fb_helper_crtc *crtc_info;
174 int connector_count;
175 int connector_info_alloc_count;
176 /**
177 * @sw_rotations:
178 * Bitmask of all rotations requested for panel-orientation which
179 * could not be handled in hardware. If only one bit is set
180 * fbdev->fbcon_rotate_hint gets set to the requested rotation.
181 */
182 int sw_rotations;
183 /**
184 * @connector_info:
185 *
186 * Array of per-connector information. Do not iterate directly, but use
187 * drm_fb_helper_for_each_connector.
188 */
189 struct drm_fb_helper_connector **connector_info;
190 const struct drm_fb_helper_funcs *funcs;
191 struct fb_info *fbdev;
192 u32 pseudo_palette[17];
193 struct drm_clip_rect dirty_clip;
194 spinlock_t dirty_lock;
195 struct work_struct dirty_work;
196 struct work_struct resume_work;
197
198 /**
199 * @lock:
200 *
201 * Top-level FBDEV helper lock. This protects all internal data
202 * structures and lists, such as @connector_info and @crtc_info.
203 *
204 * FIXME: fbdev emulation locking is a mess and long term we want to
205 * protect all helper internal state with this lock as well as reduce
206 * core KMS locking as much as possible.
207 */
208 struct mutex lock;
209
210 /**
211 * @kernel_fb_list:
212 *
213 * Entry on the global kernel_fb_helper_list, used for kgdb entry/exit.
214 */
215 struct list_head kernel_fb_list;
216
217 /**
218 * @delayed_hotplug:
219 *
220 * A hotplug was received while fbdev wasn't in control of the DRM
221 * device, i.e. another KMS master was active. The output configuration
222 * needs to be reprobe when fbdev is in control again.
223 */
224 bool delayed_hotplug;
225
226 /**
227 * @deferred_setup:
228 *
229 * If no outputs are connected (disconnected or unknown) the FB helper
230 * code will defer setup until at least one of the outputs shows up.
231 * This field keeps track of the status so that setup can be retried
232 * at every hotplug event until it succeeds eventually.
233 *
234 * Protected by @lock.
235 */
236 bool deferred_setup;
237
238 /**
239 * @preferred_bpp:
240 *
241 * Temporary storage for the driver's preferred BPP setting passed to
242 * FB helper initialization. This needs to be tracked so that deferred
243 * FB helper setup can pass this on.
244 *
245 * See also: @deferred_setup
246 */
247 int preferred_bpp;
248 };
249
250 static inline struct drm_fb_helper *
251 drm_fb_helper_from_client(struct drm_client_dev *client)
252 {
253 return container_of(client, struct drm_fb_helper, client);
254 }
255
256 /**
257 * define DRM_FB_HELPER_DEFAULT_OPS - helper define for drm drivers
258 *
259 * Helper define to register default implementations of drm_fb_helper
260 * functions. To be used in struct fb_ops of drm drivers.
261 */
262 #define DRM_FB_HELPER_DEFAULT_OPS \
263 .fb_check_var = drm_fb_helper_check_var, \
264 .fb_set_par = drm_fb_helper_set_par, \
265 .fb_setcmap = drm_fb_helper_setcmap, \
266 .fb_blank = drm_fb_helper_blank, \
267 .fb_pan_display = drm_fb_helper_pan_display, \
268 .fb_debug_enter = drm_fb_helper_debug_enter, \
269 .fb_debug_leave = drm_fb_helper_debug_leave, \
270 .fb_ioctl = drm_fb_helper_ioctl
271
272 #ifdef CONFIG_DRM_FBDEV_EMULATION
273 void drm_fb_helper_prepare(struct drm_device *dev, struct drm_fb_helper *helper,
274 const struct drm_fb_helper_funcs *funcs);
275 int drm_fb_helper_init(struct drm_device *dev,
276 struct drm_fb_helper *helper, int max_conn);
277 void drm_fb_helper_fini(struct drm_fb_helper *helper);
278 int drm_fb_helper_blank(int blank, struct fb_info *info);
279 int drm_fb_helper_pan_display(struct fb_var_screeninfo *var,
280 struct fb_info *info);
281 int drm_fb_helper_set_par(struct fb_info *info);
282 int drm_fb_helper_check_var(struct fb_var_screeninfo *var,
283 struct fb_info *info);
284
285 int drm_fb_helper_restore_fbdev_mode_unlocked(struct drm_fb_helper *fb_helper);
286
287 struct fb_info *drm_fb_helper_alloc_fbi(struct drm_fb_helper *fb_helper);
288 void drm_fb_helper_unregister_fbi(struct drm_fb_helper *fb_helper);
289 void drm_fb_helper_fill_info(struct fb_info *info,
290 struct drm_fb_helper *fb_helper,
291 struct drm_fb_helper_surface_size *sizes);
292
293 void drm_fb_helper_unlink_fbi(struct drm_fb_helper *fb_helper);
294
295 void drm_fb_helper_deferred_io(struct fb_info *info,
296 struct list_head *pagelist);
297 int drm_fb_helper_defio_init(struct drm_fb_helper *fb_helper);
298
299 ssize_t drm_fb_helper_sys_read(struct fb_info *info, char __user *buf,
300 size_t count, loff_t *ppos);
301 ssize_t drm_fb_helper_sys_write(struct fb_info *info, const char __user *buf,
302 size_t count, loff_t *ppos);
303
304 void drm_fb_helper_sys_fillrect(struct fb_info *info,
305 const struct fb_fillrect *rect);
306 void drm_fb_helper_sys_copyarea(struct fb_info *info,
307 const struct fb_copyarea *area);
308 void drm_fb_helper_sys_imageblit(struct fb_info *info,
309 const struct fb_image *image);
310
311 void drm_fb_helper_cfb_fillrect(struct fb_info *info,
312 const struct fb_fillrect *rect);
313 void drm_fb_helper_cfb_copyarea(struct fb_info *info,
314 const struct fb_copyarea *area);
315 void drm_fb_helper_cfb_imageblit(struct fb_info *info,
316 const struct fb_image *image);
317
318 void drm_fb_helper_set_suspend(struct drm_fb_helper *fb_helper, bool suspend);
319 void drm_fb_helper_set_suspend_unlocked(struct drm_fb_helper *fb_helper,
320 bool suspend);
321
322 int drm_fb_helper_setcmap(struct fb_cmap *cmap, struct fb_info *info);
323
324 int drm_fb_helper_ioctl(struct fb_info *info, unsigned int cmd,
325 unsigned long arg);
326
327 int drm_fb_helper_hotplug_event(struct drm_fb_helper *fb_helper);
328 int drm_fb_helper_initial_config(struct drm_fb_helper *fb_helper, int bpp_sel);
329 int drm_fb_helper_single_add_all_connectors(struct drm_fb_helper *fb_helper);
330 int drm_fb_helper_debug_enter(struct fb_info *info);
331 int drm_fb_helper_debug_leave(struct fb_info *info);
332 struct drm_display_mode *
333 drm_has_preferred_mode(struct drm_fb_helper_connector *fb_connector,
334 int width, int height);
335 struct drm_display_mode *
336 drm_pick_cmdline_mode(struct drm_fb_helper_connector *fb_helper_conn);
337
338 int drm_fb_helper_add_one_connector(struct drm_fb_helper *fb_helper, struct drm_connector *connector);
339 int drm_fb_helper_remove_one_connector(struct drm_fb_helper *fb_helper,
340 struct drm_connector *connector);
341
342 int drm_fb_helper_fbdev_setup(struct drm_device *dev,
343 struct drm_fb_helper *fb_helper,
344 const struct drm_fb_helper_funcs *funcs,
345 unsigned int preferred_bpp,
346 unsigned int max_conn_count);
347 void drm_fb_helper_fbdev_teardown(struct drm_device *dev);
348
349 void drm_fb_helper_lastclose(struct drm_device *dev);
350 void drm_fb_helper_output_poll_changed(struct drm_device *dev);
351
352 int drm_fb_helper_generic_probe(struct drm_fb_helper *fb_helper,
353 struct drm_fb_helper_surface_size *sizes);
354 int drm_fbdev_generic_setup(struct drm_device *dev, unsigned int preferred_bpp);
355 #else
356 static inline void drm_fb_helper_prepare(struct drm_device *dev,
357 struct drm_fb_helper *helper,
358 const struct drm_fb_helper_funcs *funcs)
359 {
360 }
361
362 static inline int drm_fb_helper_init(struct drm_device *dev,
363 struct drm_fb_helper *helper,
364 int max_conn)
365 {
366 /* So drivers can use it to free the struct */
367 helper->dev = dev;
368 dev->fb_helper = helper;
369
370 return 0;
371 }
372
373 static inline void drm_fb_helper_fini(struct drm_fb_helper *helper)
374 {
375 if (helper && helper->dev)
376 helper->dev->fb_helper = NULL;
377 }
378
379 static inline int drm_fb_helper_blank(int blank, struct fb_info *info)
380 {
381 return 0;
382 }
383
384 static inline int drm_fb_helper_pan_display(struct fb_var_screeninfo *var,
385 struct fb_info *info)
386 {
387 return 0;
388 }
389
390 static inline int drm_fb_helper_set_par(struct fb_info *info)
391 {
392 return 0;
393 }
394
395 static inline int drm_fb_helper_check_var(struct fb_var_screeninfo *var,
396 struct fb_info *info)
397 {
398 return 0;
399 }
400
401 static inline int
402 drm_fb_helper_restore_fbdev_mode_unlocked(struct drm_fb_helper *fb_helper)
403 {
404 return 0;
405 }
406
407 static inline struct fb_info *
408 drm_fb_helper_alloc_fbi(struct drm_fb_helper *fb_helper)
409 {
410 return NULL;
411 }
412
413 static inline void drm_fb_helper_unregister_fbi(struct drm_fb_helper *fb_helper)
414 {
415 }
416
417 static inline void
418 drm_fb_helper_fill_info(struct fb_info *info,
419 struct drm_fb_helper *fb_helper,
420 struct drm_fb_helper_surface_size *sizes)
421 {
422 }
423
424 static inline int drm_fb_helper_setcmap(struct fb_cmap *cmap,
425 struct fb_info *info)
426 {
427 return 0;
428 }
429
430 static inline int drm_fb_helper_ioctl(struct fb_info *info, unsigned int cmd,
431 unsigned long arg)
432 {
433 return 0;
434 }
435
436 static inline void drm_fb_helper_unlink_fbi(struct drm_fb_helper *fb_helper)
437 {
438 }
439
440 static inline void drm_fb_helper_deferred_io(struct fb_info *info,
441 struct list_head *pagelist)
442 {
443 }
444
445 static inline int drm_fb_helper_defio_init(struct drm_fb_helper *fb_helper)
446 {
447 return -ENODEV;
448 }
449
450 static inline ssize_t drm_fb_helper_sys_read(struct fb_info *info,
451 char __user *buf, size_t count,
452 loff_t *ppos)
453 {
454 return -ENODEV;
455 }
456
457 static inline ssize_t drm_fb_helper_sys_write(struct fb_info *info,
458 const char __user *buf,
459 size_t count, loff_t *ppos)
460 {
461 return -ENODEV;
462 }
463
464 static inline void drm_fb_helper_sys_fillrect(struct fb_info *info,
465 const struct fb_fillrect *rect)
466 {
467 }
468
469 static inline void drm_fb_helper_sys_copyarea(struct fb_info *info,
470 const struct fb_copyarea *area)
471 {
472 }
473
474 static inline void drm_fb_helper_sys_imageblit(struct fb_info *info,
475 const struct fb_image *image)
476 {
477 }
478
479 static inline void drm_fb_helper_cfb_fillrect(struct fb_info *info,
480 const struct fb_fillrect *rect)
481 {
482 }
483
484 static inline void drm_fb_helper_cfb_copyarea(struct fb_info *info,
485 const struct fb_copyarea *area)
486 {
487 }
488
489 static inline void drm_fb_helper_cfb_imageblit(struct fb_info *info,
490 const struct fb_image *image)
491 {
492 }
493
494 static inline void drm_fb_helper_set_suspend(struct drm_fb_helper *fb_helper,
495 bool suspend)
496 {
497 }
498
499 static inline void
500 drm_fb_helper_set_suspend_unlocked(struct drm_fb_helper *fb_helper, bool suspend)
501 {
502 }
503
504 static inline int drm_fb_helper_hotplug_event(struct drm_fb_helper *fb_helper)
505 {
506 return 0;
507 }
508
509 static inline int drm_fb_helper_initial_config(struct drm_fb_helper *fb_helper,
510 int bpp_sel)
511 {
512 return 0;
513 }
514
515 static inline int
516 drm_fb_helper_single_add_all_connectors(struct drm_fb_helper *fb_helper)
517 {
518 return 0;
519 }
520
521 static inline int drm_fb_helper_debug_enter(struct fb_info *info)
522 {
523 return 0;
524 }
525
526 static inline int drm_fb_helper_debug_leave(struct fb_info *info)
527 {
528 return 0;
529 }
530
531 static inline struct drm_display_mode *
532 drm_has_preferred_mode(struct drm_fb_helper_connector *fb_connector,
533 int width, int height)
534 {
535 return NULL;
536 }
537
538 static inline struct drm_display_mode *
539 drm_pick_cmdline_mode(struct drm_fb_helper_connector *fb_helper_conn,
540 int width, int height)
541 {
542 return NULL;
543 }
544
545 static inline int
546 drm_fb_helper_add_one_connector(struct drm_fb_helper *fb_helper,
547 struct drm_connector *connector)
548 {
549 return 0;
550 }
551
552 static inline int
553 drm_fb_helper_remove_one_connector(struct drm_fb_helper *fb_helper,
554 struct drm_connector *connector)
555 {
556 return 0;
557 }
558
559 static inline int
560 drm_fb_helper_fbdev_setup(struct drm_device *dev,
561 struct drm_fb_helper *fb_helper,
562 const struct drm_fb_helper_funcs *funcs,
563 unsigned int preferred_bpp,
564 unsigned int max_conn_count)
565 {
566 /* So drivers can use it to free the struct */
567 dev->fb_helper = fb_helper;
568
569 return 0;
570 }
571
572 static inline void drm_fb_helper_fbdev_teardown(struct drm_device *dev)
573 {
574 dev->fb_helper = NULL;
575 }
576
577 static inline void drm_fb_helper_lastclose(struct drm_device *dev)
578 {
579 }
580
581 static inline void drm_fb_helper_output_poll_changed(struct drm_device *dev)
582 {
583 }
584
585 static inline int
586 drm_fb_helper_generic_probe(struct drm_fb_helper *fb_helper,
587 struct drm_fb_helper_surface_size *sizes)
588 {
589 return 0;
590 }
591
592 static inline int
593 drm_fbdev_generic_setup(struct drm_device *dev, unsigned int preferred_bpp)
594 {
595 return 0;
596 }
597
598 #endif
599
600 /**
601 * drm_fb_helper_remove_conflicting_framebuffers - remove firmware-configured framebuffers
602 * @a: memory range, users of which are to be removed
603 * @name: requesting driver name
604 * @primary: also kick vga16fb if present
605 *
606 * This function removes framebuffer devices (initialized by firmware/bootloader)
607 * which use memory range described by @a. If @a is NULL all such devices are
608 * removed.
609 */
610 static inline int
611 drm_fb_helper_remove_conflicting_framebuffers(struct apertures_struct *a,
612 const char *name, bool primary)
613 {
614 #if IS_REACHABLE(CONFIG_FB)
615 return remove_conflicting_framebuffers(a, name, primary);
616 #else
617 return 0;
618 #endif
619 }
620
621 /**
622 * drm_fb_helper_remove_conflicting_pci_framebuffers - remove firmware-configured framebuffers for PCI devices
623 * @pdev: PCI device
624 * @resource_id: index of PCI BAR configuring framebuffer memory
625 * @name: requesting driver name
626 *
627 * This function removes framebuffer devices (eg. initialized by firmware)
628 * using memory range configured for @pdev's BAR @resource_id.
629 *
630 * The function assumes that PCI device with shadowed ROM drives a primary
631 * display and so kicks out vga16fb.
632 */
633 static inline int
634 drm_fb_helper_remove_conflicting_pci_framebuffers(struct pci_dev *pdev,
635 int resource_id,
636 const char *name)
637 {
638 #if IS_REACHABLE(CONFIG_FB)
639 return remove_conflicting_pci_framebuffers(pdev, resource_id, name);
640 #else
641 return 0;
642 #endif
643 }
644
645 #endif