2 * Copyright (c) 2006-2009 Red Hat Inc.
3 * Copyright (c) 2006-2008 Intel Corporation
4 * Copyright (c) 2007 Dave Airlie <airlied@linux.ie>
6 * DRM framebuffer helper functions
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.
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
27 * Dave Airlie <airlied@linux.ie>
28 * Jesse Barnes <jesse.barnes@intel.com>
30 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
32 #include <linux/console.h>
33 #include <linux/pci.h>
34 #include <linux/sysrq.h>
35 #include <linux/vga_switcheroo.h>
37 #include <drm/drm_atomic.h>
38 #include <drm/drm_drv.h>
39 #include <drm/drm_fb_helper.h>
40 #include <drm/drm_fourcc.h>
41 #include <drm/drm_framebuffer.h>
42 #include <drm/drm_modeset_helper_vtables.h>
43 #include <drm/drm_print.h>
44 #include <drm/drm_vblank.h>
46 #include "drm_internal.h"
48 static bool drm_fbdev_emulation
= true;
49 module_param_named(fbdev_emulation
, drm_fbdev_emulation
, bool, 0600);
50 MODULE_PARM_DESC(fbdev_emulation
,
51 "Enable legacy fbdev emulation [default=true]");
53 static int drm_fbdev_overalloc
= CONFIG_DRM_FBDEV_OVERALLOC
;
54 module_param(drm_fbdev_overalloc
, int, 0444);
55 MODULE_PARM_DESC(drm_fbdev_overalloc
,
56 "Overallocation of the fbdev buffer (%) [default="
57 __MODULE_STRING(CONFIG_DRM_FBDEV_OVERALLOC
) "]");
60 * In order to keep user-space compatibility, we want in certain use-cases
61 * to keep leaking the fbdev physical address to the user-space program
62 * handling the fbdev buffer.
64 * This is a bad habit, essentially kept to support closed-source OpenGL
65 * drivers that should really be moved into open-source upstream projects
66 * instead of using legacy physical addresses in user space to communicate
67 * with other out-of-tree kernel modules.
69 * This module_param *should* be removed as soon as possible and be
70 * considered as a broken and legacy behaviour from a modern fbdev device.
72 static bool drm_leak_fbdev_smem
;
73 #if IS_ENABLED(CONFIG_DRM_FBDEV_LEAK_PHYS_SMEM)
74 module_param_unsafe(drm_leak_fbdev_smem
, bool, 0600);
75 MODULE_PARM_DESC(drm_leak_fbdev_smem
,
76 "Allow unsafe leaking fbdev physical smem address [default=false]");
79 static LIST_HEAD(kernel_fb_helper_list
);
80 static DEFINE_MUTEX(kernel_fb_helper_lock
);
85 * The fb helper functions are useful to provide an fbdev on top of a drm kernel
86 * mode setting driver. They can be used mostly independently from the crtc
87 * helper functions used by many drivers to implement the kernel mode setting
90 * Drivers that support a dumb buffer with a virtual address and mmap support,
91 * should try out the generic fbdev emulation using drm_fbdev_generic_setup().
92 * It will automatically set up deferred I/O if the driver requires a shadow
95 * Existing fbdev implementations should restore the fbdev console by using
96 * drm_fb_helper_lastclose() as their &drm_driver.lastclose callback.
97 * They should also notify the fb helper code from updates to the output
98 * configuration by using drm_fb_helper_output_poll_changed() as their
99 * &drm_mode_config_funcs.output_poll_changed callback. New implementations
100 * of fbdev should be build on top of struct &drm_client_funcs, which handles
101 * this automatically. Setting the old callbacks should be avoided.
103 * For suspend/resume consider using drm_mode_config_helper_suspend() and
104 * drm_mode_config_helper_resume() which takes care of fbdev as well.
106 * All other functions exported by the fb helper library can be used to
107 * implement the fbdev driver interface by the driver.
109 * It is possible, though perhaps somewhat tricky, to implement race-free
110 * hotplug detection using the fbdev helpers. The drm_fb_helper_prepare()
111 * helper must be called first to initialize the minimum required to make
112 * hotplug detection work. Drivers also need to make sure to properly set up
113 * the &drm_mode_config.funcs member. After calling drm_kms_helper_poll_init()
114 * it is safe to enable interrupts and start processing hotplug events. At the
115 * same time, drivers should initialize all modeset objects such as CRTCs,
116 * encoders and connectors. To finish up the fbdev helper initialization, the
117 * drm_fb_helper_init() function is called. To probe for all attached displays
118 * and set up an initial configuration using the detected hardware, drivers
119 * should call drm_fb_helper_initial_config().
121 * If &drm_framebuffer_funcs.dirty is set, the
122 * drm_fb_helper_{cfb,sys}_{write,fillrect,copyarea,imageblit} functions will
123 * accumulate changes and schedule &drm_fb_helper.dirty_work to run right
124 * away. This worker then calls the dirty() function ensuring that it will
125 * always run in process context since the fb_*() function could be running in
126 * atomic context. If drm_fb_helper_deferred_io() is used as the deferred_io
127 * callback it will also schedule dirty_work with the damage collected from the
130 * Deferred I/O is not compatible with SHMEM. Such drivers should request an
131 * fbdev shadow buffer and call drm_fbdev_generic_setup() instead.
134 static void drm_fb_helper_restore_lut_atomic(struct drm_crtc
*crtc
)
136 uint16_t *r_base
, *g_base
, *b_base
;
138 if (crtc
->funcs
->gamma_set
== NULL
)
141 r_base
= crtc
->gamma_store
;
142 g_base
= r_base
+ crtc
->gamma_size
;
143 b_base
= g_base
+ crtc
->gamma_size
;
145 crtc
->funcs
->gamma_set(crtc
, r_base
, g_base
, b_base
,
146 crtc
->gamma_size
, NULL
);
150 * drm_fb_helper_debug_enter - implementation for &fb_ops.fb_debug_enter
151 * @info: fbdev registered by the helper
153 int drm_fb_helper_debug_enter(struct fb_info
*info
)
155 struct drm_fb_helper
*helper
= info
->par
;
156 const struct drm_crtc_helper_funcs
*funcs
;
157 struct drm_mode_set
*mode_set
;
159 list_for_each_entry(helper
, &kernel_fb_helper_list
, kernel_fb_list
) {
160 mutex_lock(&helper
->client
.modeset_mutex
);
161 drm_client_for_each_modeset(mode_set
, &helper
->client
) {
162 if (!mode_set
->crtc
->enabled
)
165 funcs
= mode_set
->crtc
->helper_private
;
166 if (funcs
->mode_set_base_atomic
== NULL
)
169 if (drm_drv_uses_atomic_modeset(mode_set
->crtc
->dev
))
172 funcs
->mode_set_base_atomic(mode_set
->crtc
,
176 ENTER_ATOMIC_MODE_SET
);
178 mutex_unlock(&helper
->client
.modeset_mutex
);
183 EXPORT_SYMBOL(drm_fb_helper_debug_enter
);
186 * drm_fb_helper_debug_leave - implementation for &fb_ops.fb_debug_leave
187 * @info: fbdev registered by the helper
189 int drm_fb_helper_debug_leave(struct fb_info
*info
)
191 struct drm_fb_helper
*helper
= info
->par
;
192 struct drm_client_dev
*client
= &helper
->client
;
193 struct drm_device
*dev
= helper
->dev
;
194 struct drm_crtc
*crtc
;
195 const struct drm_crtc_helper_funcs
*funcs
;
196 struct drm_mode_set
*mode_set
;
197 struct drm_framebuffer
*fb
;
199 mutex_lock(&client
->modeset_mutex
);
200 drm_client_for_each_modeset(mode_set
, client
) {
201 crtc
= mode_set
->crtc
;
202 if (drm_drv_uses_atomic_modeset(crtc
->dev
))
205 funcs
= crtc
->helper_private
;
206 fb
= crtc
->primary
->fb
;
212 drm_err(dev
, "no fb to restore?\n");
216 if (funcs
->mode_set_base_atomic
== NULL
)
219 drm_fb_helper_restore_lut_atomic(mode_set
->crtc
);
220 funcs
->mode_set_base_atomic(mode_set
->crtc
, fb
, crtc
->x
,
221 crtc
->y
, LEAVE_ATOMIC_MODE_SET
);
223 mutex_unlock(&client
->modeset_mutex
);
227 EXPORT_SYMBOL(drm_fb_helper_debug_leave
);
230 __drm_fb_helper_restore_fbdev_mode_unlocked(struct drm_fb_helper
*fb_helper
,
236 if (!drm_fbdev_emulation
|| !fb_helper
)
239 if (READ_ONCE(fb_helper
->deferred_setup
))
242 mutex_lock(&fb_helper
->lock
);
245 * Yes this is the _locked version which expects the master lock
246 * to be held. But for forced restores we're intentionally
247 * racing here, see drm_fb_helper_set_par().
249 ret
= drm_client_modeset_commit_locked(&fb_helper
->client
);
251 ret
= drm_client_modeset_commit(&fb_helper
->client
);
254 do_delayed
= fb_helper
->delayed_hotplug
;
256 fb_helper
->delayed_hotplug
= false;
257 mutex_unlock(&fb_helper
->lock
);
260 drm_fb_helper_hotplug_event(fb_helper
);
266 * drm_fb_helper_restore_fbdev_mode_unlocked - restore fbdev configuration
267 * @fb_helper: driver-allocated fbdev helper, can be NULL
269 * This should be called from driver's drm &drm_driver.lastclose callback
270 * when implementing an fbcon on top of kms using this helper. This ensures that
271 * the user isn't greeted with a black screen when e.g. X dies.
274 * Zero if everything went ok, negative error code otherwise.
276 int drm_fb_helper_restore_fbdev_mode_unlocked(struct drm_fb_helper
*fb_helper
)
278 return __drm_fb_helper_restore_fbdev_mode_unlocked(fb_helper
, false);
280 EXPORT_SYMBOL(drm_fb_helper_restore_fbdev_mode_unlocked
);
282 #ifdef CONFIG_MAGIC_SYSRQ
283 /* emergency restore, don't bother with error reporting */
284 static void drm_fb_helper_restore_work_fn(struct work_struct
*ignored
)
286 struct drm_fb_helper
*helper
;
288 mutex_lock(&kernel_fb_helper_lock
);
289 list_for_each_entry(helper
, &kernel_fb_helper_list
, kernel_fb_list
) {
290 struct drm_device
*dev
= helper
->dev
;
292 if (dev
->switch_power_state
== DRM_SWITCH_POWER_OFF
)
295 mutex_lock(&helper
->lock
);
296 drm_client_modeset_commit_locked(&helper
->client
);
297 mutex_unlock(&helper
->lock
);
299 mutex_unlock(&kernel_fb_helper_lock
);
302 static DECLARE_WORK(drm_fb_helper_restore_work
, drm_fb_helper_restore_work_fn
);
304 static void drm_fb_helper_sysrq(u8 dummy1
)
306 schedule_work(&drm_fb_helper_restore_work
);
309 static const struct sysrq_key_op sysrq_drm_fb_helper_restore_op
= {
310 .handler
= drm_fb_helper_sysrq
,
311 .help_msg
= "force-fb(v)",
312 .action_msg
= "Restore framebuffer console",
315 static const struct sysrq_key_op sysrq_drm_fb_helper_restore_op
= { };
318 static void drm_fb_helper_dpms(struct fb_info
*info
, int dpms_mode
)
320 struct drm_fb_helper
*fb_helper
= info
->par
;
322 mutex_lock(&fb_helper
->lock
);
323 drm_client_modeset_dpms(&fb_helper
->client
, dpms_mode
);
324 mutex_unlock(&fb_helper
->lock
);
328 * drm_fb_helper_blank - implementation for &fb_ops.fb_blank
329 * @blank: desired blanking state
330 * @info: fbdev registered by the helper
332 int drm_fb_helper_blank(int blank
, struct fb_info
*info
)
334 if (oops_in_progress
)
338 /* Display: On; HSync: On, VSync: On */
339 case FB_BLANK_UNBLANK
:
340 drm_fb_helper_dpms(info
, DRM_MODE_DPMS_ON
);
342 /* Display: Off; HSync: On, VSync: On */
343 case FB_BLANK_NORMAL
:
344 drm_fb_helper_dpms(info
, DRM_MODE_DPMS_STANDBY
);
346 /* Display: Off; HSync: Off, VSync: On */
347 case FB_BLANK_HSYNC_SUSPEND
:
348 drm_fb_helper_dpms(info
, DRM_MODE_DPMS_STANDBY
);
350 /* Display: Off; HSync: On, VSync: Off */
351 case FB_BLANK_VSYNC_SUSPEND
:
352 drm_fb_helper_dpms(info
, DRM_MODE_DPMS_SUSPEND
);
354 /* Display: Off; HSync: Off, VSync: Off */
355 case FB_BLANK_POWERDOWN
:
356 drm_fb_helper_dpms(info
, DRM_MODE_DPMS_OFF
);
361 EXPORT_SYMBOL(drm_fb_helper_blank
);
363 static void drm_fb_helper_resume_worker(struct work_struct
*work
)
365 struct drm_fb_helper
*helper
= container_of(work
, struct drm_fb_helper
,
369 fb_set_suspend(helper
->info
, 0);
373 static void drm_fb_helper_fb_dirty(struct drm_fb_helper
*helper
)
375 struct drm_device
*dev
= helper
->dev
;
376 struct drm_clip_rect
*clip
= &helper
->damage_clip
;
377 struct drm_clip_rect clip_copy
;
381 if (drm_WARN_ON_ONCE(dev
, !helper
->funcs
->fb_dirty
))
384 spin_lock_irqsave(&helper
->damage_lock
, flags
);
386 clip
->x1
= clip
->y1
= ~0;
387 clip
->x2
= clip
->y2
= 0;
388 spin_unlock_irqrestore(&helper
->damage_lock
, flags
);
390 ret
= helper
->funcs
->fb_dirty(helper
, &clip_copy
);
398 * Restore damage clip rectangle on errors. The next run
399 * of the damage worker will perform the update.
401 spin_lock_irqsave(&helper
->damage_lock
, flags
);
402 clip
->x1
= min_t(u32
, clip
->x1
, clip_copy
.x1
);
403 clip
->y1
= min_t(u32
, clip
->y1
, clip_copy
.y1
);
404 clip
->x2
= max_t(u32
, clip
->x2
, clip_copy
.x2
);
405 clip
->y2
= max_t(u32
, clip
->y2
, clip_copy
.y2
);
406 spin_unlock_irqrestore(&helper
->damage_lock
, flags
);
409 static void drm_fb_helper_damage_work(struct work_struct
*work
)
411 struct drm_fb_helper
*helper
= container_of(work
, struct drm_fb_helper
, damage_work
);
413 drm_fb_helper_fb_dirty(helper
);
417 * drm_fb_helper_prepare - setup a drm_fb_helper structure
419 * @helper: driver-allocated fbdev helper structure to set up
420 * @preferred_bpp: Preferred bits per pixel for the device.
421 * @funcs: pointer to structure of functions associate with this helper
423 * Sets up the bare minimum to make the framebuffer helper usable. This is
424 * useful to implement race-free initialization of the polling helpers.
426 void drm_fb_helper_prepare(struct drm_device
*dev
, struct drm_fb_helper
*helper
,
427 unsigned int preferred_bpp
,
428 const struct drm_fb_helper_funcs
*funcs
)
431 * Pick a preferred bpp of 32 if no value has been given. This
432 * will select XRGB8888 for the framebuffer formats. All drivers
433 * have to support XRGB8888 for backwards compatibility with legacy
434 * userspace, so it's the safe choice here.
436 * TODO: Replace struct drm_mode_config.preferred_depth and this
437 * bpp value with a preferred format that is given as struct
438 * drm_format_info. Then derive all other values from the
444 INIT_LIST_HEAD(&helper
->kernel_fb_list
);
445 spin_lock_init(&helper
->damage_lock
);
446 INIT_WORK(&helper
->resume_work
, drm_fb_helper_resume_worker
);
447 INIT_WORK(&helper
->damage_work
, drm_fb_helper_damage_work
);
448 helper
->damage_clip
.x1
= helper
->damage_clip
.y1
= ~0;
449 mutex_init(&helper
->lock
);
450 helper
->funcs
= funcs
;
452 helper
->preferred_bpp
= preferred_bpp
;
454 EXPORT_SYMBOL(drm_fb_helper_prepare
);
457 * drm_fb_helper_unprepare - clean up a drm_fb_helper structure
458 * @fb_helper: driver-allocated fbdev helper structure to set up
460 * Cleans up the framebuffer helper. Inverse of drm_fb_helper_prepare().
462 void drm_fb_helper_unprepare(struct drm_fb_helper
*fb_helper
)
464 mutex_destroy(&fb_helper
->lock
);
466 EXPORT_SYMBOL(drm_fb_helper_unprepare
);
469 * drm_fb_helper_init - initialize a &struct drm_fb_helper
471 * @fb_helper: driver-allocated fbdev helper structure to initialize
473 * This allocates the structures for the fbdev helper with the given limits.
474 * Note that this won't yet touch the hardware (through the driver interfaces)
475 * nor register the fbdev. This is only done in drm_fb_helper_initial_config()
476 * to allow driver writes more control over the exact init sequence.
478 * Drivers must call drm_fb_helper_prepare() before calling this function.
481 * Zero if everything went ok, nonzero otherwise.
483 int drm_fb_helper_init(struct drm_device
*dev
,
484 struct drm_fb_helper
*fb_helper
)
489 * If this is not the generic fbdev client, initialize a drm_client
490 * without callbacks so we can use the modesets.
492 if (!fb_helper
->client
.funcs
) {
493 ret
= drm_client_init(dev
, &fb_helper
->client
, "drm_fb_helper", NULL
);
498 dev
->fb_helper
= fb_helper
;
502 EXPORT_SYMBOL(drm_fb_helper_init
);
505 * drm_fb_helper_alloc_info - allocate fb_info and some of its members
506 * @fb_helper: driver-allocated fbdev helper
508 * A helper to alloc fb_info and the member cmap. Called by the driver
509 * within the fb_probe fb_helper callback function. Drivers do not
510 * need to release the allocated fb_info structure themselves, this is
511 * automatically done when calling drm_fb_helper_fini().
514 * fb_info pointer if things went okay, pointer containing error code
517 struct fb_info
*drm_fb_helper_alloc_info(struct drm_fb_helper
*fb_helper
)
519 struct device
*dev
= fb_helper
->dev
->dev
;
520 struct fb_info
*info
;
523 info
= framebuffer_alloc(0, dev
);
525 return ERR_PTR(-ENOMEM
);
527 ret
= fb_alloc_cmap(&info
->cmap
, 256, 0);
531 fb_helper
->info
= info
;
532 info
->skip_vt_switch
= true;
537 framebuffer_release(info
);
540 EXPORT_SYMBOL(drm_fb_helper_alloc_info
);
543 * drm_fb_helper_release_info - release fb_info and its members
544 * @fb_helper: driver-allocated fbdev helper
546 * A helper to release fb_info and the member cmap. Drivers do not
547 * need to release the allocated fb_info structure themselves, this is
548 * automatically done when calling drm_fb_helper_fini().
550 void drm_fb_helper_release_info(struct drm_fb_helper
*fb_helper
)
552 struct fb_info
*info
= fb_helper
->info
;
557 fb_helper
->info
= NULL
;
560 fb_dealloc_cmap(&info
->cmap
);
561 framebuffer_release(info
);
563 EXPORT_SYMBOL(drm_fb_helper_release_info
);
566 * drm_fb_helper_unregister_info - unregister fb_info framebuffer device
567 * @fb_helper: driver-allocated fbdev helper, can be NULL
569 * A wrapper around unregister_framebuffer, to release the fb_info
570 * framebuffer device. This must be called before releasing all resources for
571 * @fb_helper by calling drm_fb_helper_fini().
573 void drm_fb_helper_unregister_info(struct drm_fb_helper
*fb_helper
)
575 if (fb_helper
&& fb_helper
->info
)
576 unregister_framebuffer(fb_helper
->info
);
578 EXPORT_SYMBOL(drm_fb_helper_unregister_info
);
581 * drm_fb_helper_fini - finialize a &struct drm_fb_helper
582 * @fb_helper: driver-allocated fbdev helper, can be NULL
584 * This cleans up all remaining resources associated with @fb_helper.
586 void drm_fb_helper_fini(struct drm_fb_helper
*fb_helper
)
591 fb_helper
->dev
->fb_helper
= NULL
;
593 if (!drm_fbdev_emulation
)
596 cancel_work_sync(&fb_helper
->resume_work
);
597 cancel_work_sync(&fb_helper
->damage_work
);
599 drm_fb_helper_release_info(fb_helper
);
601 mutex_lock(&kernel_fb_helper_lock
);
602 if (!list_empty(&fb_helper
->kernel_fb_list
)) {
603 list_del(&fb_helper
->kernel_fb_list
);
604 if (list_empty(&kernel_fb_helper_list
))
605 unregister_sysrq_key('v', &sysrq_drm_fb_helper_restore_op
);
607 mutex_unlock(&kernel_fb_helper_lock
);
609 if (!fb_helper
->client
.funcs
)
610 drm_client_release(&fb_helper
->client
);
612 EXPORT_SYMBOL(drm_fb_helper_fini
);
614 static void drm_fb_helper_add_damage_clip(struct drm_fb_helper
*helper
, u32 x
, u32 y
,
615 u32 width
, u32 height
)
617 struct drm_clip_rect
*clip
= &helper
->damage_clip
;
620 spin_lock_irqsave(&helper
->damage_lock
, flags
);
621 clip
->x1
= min_t(u32
, clip
->x1
, x
);
622 clip
->y1
= min_t(u32
, clip
->y1
, y
);
623 clip
->x2
= max_t(u32
, clip
->x2
, x
+ width
);
624 clip
->y2
= max_t(u32
, clip
->y2
, y
+ height
);
625 spin_unlock_irqrestore(&helper
->damage_lock
, flags
);
628 static void drm_fb_helper_damage(struct drm_fb_helper
*helper
, u32 x
, u32 y
,
629 u32 width
, u32 height
)
631 drm_fb_helper_add_damage_clip(helper
, x
, y
, width
, height
);
633 schedule_work(&helper
->damage_work
);
637 * Convert memory region into area of scanlines and pixels per
638 * scanline. The parameters off and len must not reach beyond
639 * the end of the framebuffer.
641 static void drm_fb_helper_memory_range_to_clip(struct fb_info
*info
, off_t off
, size_t len
,
642 struct drm_rect
*clip
)
644 u32 line_length
= info
->fix
.line_length
;
645 u32 fb_height
= info
->var
.yres
;
646 off_t end
= off
+ len
;
648 u32 y1
= off
/ line_length
;
649 u32 x2
= info
->var
.xres
;
650 u32 y2
= DIV_ROUND_UP(end
, line_length
);
652 /* Don't allow any of them beyond the bottom bound of display area */
658 if ((y2
- y1
) == 1) {
660 * We've only written to a single scanline. Try to reduce
661 * the number of horizontal pixels that need an update.
663 off_t bit_off
= (off
% line_length
) * 8;
664 off_t bit_end
= (end
% line_length
) * 8;
666 x1
= bit_off
/ info
->var
.bits_per_pixel
;
667 x2
= DIV_ROUND_UP(bit_end
, info
->var
.bits_per_pixel
);
670 drm_rect_init(clip
, x1
, y1
, x2
- x1
, y2
- y1
);
673 /* Don't use in new code. */
674 void drm_fb_helper_damage_range(struct fb_info
*info
, off_t off
, size_t len
)
676 struct drm_fb_helper
*fb_helper
= info
->par
;
677 struct drm_rect damage_area
;
679 drm_fb_helper_memory_range_to_clip(info
, off
, len
, &damage_area
);
680 drm_fb_helper_damage(fb_helper
, damage_area
.x1
, damage_area
.y1
,
681 drm_rect_width(&damage_area
),
682 drm_rect_height(&damage_area
));
684 EXPORT_SYMBOL(drm_fb_helper_damage_range
);
686 /* Don't use in new code. */
687 void drm_fb_helper_damage_area(struct fb_info
*info
, u32 x
, u32 y
, u32 width
, u32 height
)
689 struct drm_fb_helper
*fb_helper
= info
->par
;
691 drm_fb_helper_damage(fb_helper
, x
, y
, width
, height
);
693 EXPORT_SYMBOL(drm_fb_helper_damage_area
);
696 * drm_fb_helper_deferred_io() - fbdev deferred_io callback function
697 * @info: fb_info struct pointer
698 * @pagereflist: list of mmap framebuffer pages that have to be flushed
700 * This function is used as the &fb_deferred_io.deferred_io
701 * callback function for flushing the fbdev mmap writes.
703 void drm_fb_helper_deferred_io(struct fb_info
*info
, struct list_head
*pagereflist
)
705 struct drm_fb_helper
*helper
= info
->par
;
706 unsigned long start
, end
, min_off
, max_off
, total_size
;
707 struct fb_deferred_io_pageref
*pageref
;
708 struct drm_rect damage_area
;
712 list_for_each_entry(pageref
, pagereflist
, list
) {
713 start
= pageref
->offset
;
714 end
= start
+ PAGE_SIZE
;
715 min_off
= min(min_off
, start
);
716 max_off
= max(max_off
, end
);
720 * As we can only track pages, we might reach beyond the end
721 * of the screen and account for non-existing scanlines. Hence,
722 * keep the covered memory area within the screen buffer.
724 if (info
->screen_size
)
725 total_size
= info
->screen_size
;
727 total_size
= info
->fix
.smem_len
;
728 max_off
= min(max_off
, total_size
);
730 if (min_off
< max_off
) {
731 drm_fb_helper_memory_range_to_clip(info
, min_off
, max_off
- min_off
, &damage_area
);
732 drm_fb_helper_damage(helper
, damage_area
.x1
, damage_area
.y1
,
733 drm_rect_width(&damage_area
),
734 drm_rect_height(&damage_area
));
737 EXPORT_SYMBOL(drm_fb_helper_deferred_io
);
740 * drm_fb_helper_set_suspend - wrapper around fb_set_suspend
741 * @fb_helper: driver-allocated fbdev helper, can be NULL
742 * @suspend: whether to suspend or resume
744 * A wrapper around fb_set_suspend implemented by fbdev core.
745 * Use drm_fb_helper_set_suspend_unlocked() if you don't need to take
748 void drm_fb_helper_set_suspend(struct drm_fb_helper
*fb_helper
, bool suspend
)
750 if (fb_helper
&& fb_helper
->info
)
751 fb_set_suspend(fb_helper
->info
, suspend
);
753 EXPORT_SYMBOL(drm_fb_helper_set_suspend
);
756 * drm_fb_helper_set_suspend_unlocked - wrapper around fb_set_suspend that also
757 * takes the console lock
758 * @fb_helper: driver-allocated fbdev helper, can be NULL
759 * @suspend: whether to suspend or resume
761 * A wrapper around fb_set_suspend() that takes the console lock. If the lock
762 * isn't available on resume, a worker is tasked with waiting for the lock
763 * to become available. The console lock can be pretty contented on resume
764 * due to all the printk activity.
766 * This function can be called multiple times with the same state since
767 * &fb_info.state is checked to see if fbdev is running or not before locking.
769 * Use drm_fb_helper_set_suspend() if you need to take the lock yourself.
771 void drm_fb_helper_set_suspend_unlocked(struct drm_fb_helper
*fb_helper
,
774 if (!fb_helper
|| !fb_helper
->info
)
777 /* make sure there's no pending/ongoing resume */
778 flush_work(&fb_helper
->resume_work
);
781 if (fb_helper
->info
->state
!= FBINFO_STATE_RUNNING
)
787 if (fb_helper
->info
->state
== FBINFO_STATE_RUNNING
)
790 if (!console_trylock()) {
791 schedule_work(&fb_helper
->resume_work
);
796 fb_set_suspend(fb_helper
->info
, suspend
);
799 EXPORT_SYMBOL(drm_fb_helper_set_suspend_unlocked
);
801 static int setcmap_pseudo_palette(struct fb_cmap
*cmap
, struct fb_info
*info
)
803 u32
*palette
= (u32
*)info
->pseudo_palette
;
806 if (cmap
->start
+ cmap
->len
> 16)
809 for (i
= 0; i
< cmap
->len
; ++i
) {
810 u16 red
= cmap
->red
[i
];
811 u16 green
= cmap
->green
[i
];
812 u16 blue
= cmap
->blue
[i
];
815 red
>>= 16 - info
->var
.red
.length
;
816 green
>>= 16 - info
->var
.green
.length
;
817 blue
>>= 16 - info
->var
.blue
.length
;
818 value
= (red
<< info
->var
.red
.offset
) |
819 (green
<< info
->var
.green
.offset
) |
820 (blue
<< info
->var
.blue
.offset
);
821 if (info
->var
.transp
.length
> 0) {
822 u32 mask
= (1 << info
->var
.transp
.length
) - 1;
824 mask
<<= info
->var
.transp
.offset
;
827 palette
[cmap
->start
+ i
] = value
;
833 static int setcmap_legacy(struct fb_cmap
*cmap
, struct fb_info
*info
)
835 struct drm_fb_helper
*fb_helper
= info
->par
;
836 struct drm_mode_set
*modeset
;
837 struct drm_crtc
*crtc
;
841 drm_modeset_lock_all(fb_helper
->dev
);
842 drm_client_for_each_modeset(modeset
, &fb_helper
->client
) {
843 crtc
= modeset
->crtc
;
844 if (!crtc
->funcs
->gamma_set
|| !crtc
->gamma_size
) {
849 if (cmap
->start
+ cmap
->len
> crtc
->gamma_size
) {
854 r
= crtc
->gamma_store
;
855 g
= r
+ crtc
->gamma_size
;
856 b
= g
+ crtc
->gamma_size
;
858 memcpy(r
+ cmap
->start
, cmap
->red
, cmap
->len
* sizeof(*r
));
859 memcpy(g
+ cmap
->start
, cmap
->green
, cmap
->len
* sizeof(*g
));
860 memcpy(b
+ cmap
->start
, cmap
->blue
, cmap
->len
* sizeof(*b
));
862 ret
= crtc
->funcs
->gamma_set(crtc
, r
, g
, b
,
863 crtc
->gamma_size
, NULL
);
868 drm_modeset_unlock_all(fb_helper
->dev
);
873 static struct drm_property_blob
*setcmap_new_gamma_lut(struct drm_crtc
*crtc
,
874 struct fb_cmap
*cmap
)
876 struct drm_device
*dev
= crtc
->dev
;
877 struct drm_property_blob
*gamma_lut
;
878 struct drm_color_lut
*lut
;
879 int size
= crtc
->gamma_size
;
882 if (!size
|| cmap
->start
+ cmap
->len
> size
)
883 return ERR_PTR(-EINVAL
);
885 gamma_lut
= drm_property_create_blob(dev
, sizeof(*lut
) * size
, NULL
);
886 if (IS_ERR(gamma_lut
))
889 lut
= gamma_lut
->data
;
890 if (cmap
->start
|| cmap
->len
!= size
) {
891 u16
*r
= crtc
->gamma_store
;
892 u16
*g
= r
+ crtc
->gamma_size
;
893 u16
*b
= g
+ crtc
->gamma_size
;
895 for (i
= 0; i
< cmap
->start
; i
++) {
900 for (i
= cmap
->start
+ cmap
->len
; i
< size
; i
++) {
907 for (i
= 0; i
< cmap
->len
; i
++) {
908 lut
[cmap
->start
+ i
].red
= cmap
->red
[i
];
909 lut
[cmap
->start
+ i
].green
= cmap
->green
[i
];
910 lut
[cmap
->start
+ i
].blue
= cmap
->blue
[i
];
916 static int setcmap_atomic(struct fb_cmap
*cmap
, struct fb_info
*info
)
918 struct drm_fb_helper
*fb_helper
= info
->par
;
919 struct drm_device
*dev
= fb_helper
->dev
;
920 struct drm_property_blob
*gamma_lut
= NULL
;
921 struct drm_modeset_acquire_ctx ctx
;
922 struct drm_crtc_state
*crtc_state
;
923 struct drm_atomic_state
*state
;
924 struct drm_mode_set
*modeset
;
925 struct drm_crtc
*crtc
;
930 drm_modeset_acquire_init(&ctx
, 0);
932 state
= drm_atomic_state_alloc(dev
);
938 state
->acquire_ctx
= &ctx
;
940 drm_client_for_each_modeset(modeset
, &fb_helper
->client
) {
941 crtc
= modeset
->crtc
;
944 gamma_lut
= setcmap_new_gamma_lut(crtc
, cmap
);
945 if (IS_ERR(gamma_lut
)) {
946 ret
= PTR_ERR(gamma_lut
);
951 crtc_state
= drm_atomic_get_crtc_state(state
, crtc
);
952 if (IS_ERR(crtc_state
)) {
953 ret
= PTR_ERR(crtc_state
);
958 * FIXME: This always uses gamma_lut. Some HW have only
959 * degamma_lut, in which case we should reset gamma_lut and set
960 * degamma_lut. See drm_crtc_legacy_gamma_set().
962 replaced
= drm_property_replace_blob(&crtc_state
->degamma_lut
,
964 replaced
|= drm_property_replace_blob(&crtc_state
->ctm
, NULL
);
965 replaced
|= drm_property_replace_blob(&crtc_state
->gamma_lut
,
967 crtc_state
->color_mgmt_changed
|= replaced
;
970 ret
= drm_atomic_commit(state
);
974 drm_client_for_each_modeset(modeset
, &fb_helper
->client
) {
975 crtc
= modeset
->crtc
;
977 r
= crtc
->gamma_store
;
978 g
= r
+ crtc
->gamma_size
;
979 b
= g
+ crtc
->gamma_size
;
981 memcpy(r
+ cmap
->start
, cmap
->red
, cmap
->len
* sizeof(*r
));
982 memcpy(g
+ cmap
->start
, cmap
->green
, cmap
->len
* sizeof(*g
));
983 memcpy(b
+ cmap
->start
, cmap
->blue
, cmap
->len
* sizeof(*b
));
990 drm_property_blob_put(gamma_lut
);
991 drm_atomic_state_put(state
);
993 drm_modeset_drop_locks(&ctx
);
994 drm_modeset_acquire_fini(&ctx
);
999 drm_atomic_state_clear(state
);
1000 drm_modeset_backoff(&ctx
);
1005 * drm_fb_helper_setcmap - implementation for &fb_ops.fb_setcmap
1006 * @cmap: cmap to set
1007 * @info: fbdev registered by the helper
1009 int drm_fb_helper_setcmap(struct fb_cmap
*cmap
, struct fb_info
*info
)
1011 struct drm_fb_helper
*fb_helper
= info
->par
;
1012 struct drm_device
*dev
= fb_helper
->dev
;
1015 if (oops_in_progress
)
1018 mutex_lock(&fb_helper
->lock
);
1020 if (!drm_master_internal_acquire(dev
)) {
1025 mutex_lock(&fb_helper
->client
.modeset_mutex
);
1026 if (info
->fix
.visual
== FB_VISUAL_TRUECOLOR
)
1027 ret
= setcmap_pseudo_palette(cmap
, info
);
1028 else if (drm_drv_uses_atomic_modeset(fb_helper
->dev
))
1029 ret
= setcmap_atomic(cmap
, info
);
1031 ret
= setcmap_legacy(cmap
, info
);
1032 mutex_unlock(&fb_helper
->client
.modeset_mutex
);
1034 drm_master_internal_release(dev
);
1036 mutex_unlock(&fb_helper
->lock
);
1040 EXPORT_SYMBOL(drm_fb_helper_setcmap
);
1043 * drm_fb_helper_ioctl - legacy ioctl implementation
1044 * @info: fbdev registered by the helper
1045 * @cmd: ioctl command
1046 * @arg: ioctl argument
1048 * A helper to implement the standard fbdev ioctl. Only
1049 * FBIO_WAITFORVSYNC is implemented for now.
1051 int drm_fb_helper_ioctl(struct fb_info
*info
, unsigned int cmd
,
1054 struct drm_fb_helper
*fb_helper
= info
->par
;
1055 struct drm_device
*dev
= fb_helper
->dev
;
1056 struct drm_crtc
*crtc
;
1059 mutex_lock(&fb_helper
->lock
);
1060 if (!drm_master_internal_acquire(dev
)) {
1066 case FBIO_WAITFORVSYNC
:
1068 * Only consider the first CRTC.
1070 * This ioctl is supposed to take the CRTC number as
1071 * an argument, but in fbdev times, what that number
1072 * was supposed to be was quite unclear, different
1073 * drivers were passing that argument differently
1074 * (some by reference, some by value), and most of the
1075 * userspace applications were just hardcoding 0 as an
1078 * The first CRTC should be the integrated panel on
1079 * most drivers, so this is the best choice we can
1080 * make. If we're not smart enough here, one should
1081 * just consider switch the userspace to KMS.
1083 crtc
= fb_helper
->client
.modesets
[0].crtc
;
1086 * Only wait for a vblank event if the CRTC is
1087 * enabled, otherwise just don't do anythintg,
1088 * not even report an error.
1090 ret
= drm_crtc_vblank_get(crtc
);
1092 drm_crtc_wait_one_vblank(crtc
);
1093 drm_crtc_vblank_put(crtc
);
1102 drm_master_internal_release(dev
);
1104 mutex_unlock(&fb_helper
->lock
);
1107 EXPORT_SYMBOL(drm_fb_helper_ioctl
);
1109 static bool drm_fb_pixel_format_equal(const struct fb_var_screeninfo
*var_1
,
1110 const struct fb_var_screeninfo
*var_2
)
1112 return var_1
->bits_per_pixel
== var_2
->bits_per_pixel
&&
1113 var_1
->grayscale
== var_2
->grayscale
&&
1114 var_1
->red
.offset
== var_2
->red
.offset
&&
1115 var_1
->red
.length
== var_2
->red
.length
&&
1116 var_1
->red
.msb_right
== var_2
->red
.msb_right
&&
1117 var_1
->green
.offset
== var_2
->green
.offset
&&
1118 var_1
->green
.length
== var_2
->green
.length
&&
1119 var_1
->green
.msb_right
== var_2
->green
.msb_right
&&
1120 var_1
->blue
.offset
== var_2
->blue
.offset
&&
1121 var_1
->blue
.length
== var_2
->blue
.length
&&
1122 var_1
->blue
.msb_right
== var_2
->blue
.msb_right
&&
1123 var_1
->transp
.offset
== var_2
->transp
.offset
&&
1124 var_1
->transp
.length
== var_2
->transp
.length
&&
1125 var_1
->transp
.msb_right
== var_2
->transp
.msb_right
;
1128 static void drm_fb_helper_fill_pixel_fmt(struct fb_var_screeninfo
*var
,
1129 const struct drm_format_info
*format
)
1131 u8 depth
= format
->depth
;
1133 if (format
->is_color_indexed
) {
1134 var
->red
.offset
= 0;
1135 var
->green
.offset
= 0;
1136 var
->blue
.offset
= 0;
1137 var
->red
.length
= depth
;
1138 var
->green
.length
= depth
;
1139 var
->blue
.length
= depth
;
1140 var
->transp
.offset
= 0;
1141 var
->transp
.length
= 0;
1147 var
->red
.offset
= 10;
1148 var
->green
.offset
= 5;
1149 var
->blue
.offset
= 0;
1150 var
->red
.length
= 5;
1151 var
->green
.length
= 5;
1152 var
->blue
.length
= 5;
1153 var
->transp
.offset
= 15;
1154 var
->transp
.length
= 1;
1157 var
->red
.offset
= 11;
1158 var
->green
.offset
= 5;
1159 var
->blue
.offset
= 0;
1160 var
->red
.length
= 5;
1161 var
->green
.length
= 6;
1162 var
->blue
.length
= 5;
1163 var
->transp
.offset
= 0;
1166 var
->red
.offset
= 16;
1167 var
->green
.offset
= 8;
1168 var
->blue
.offset
= 0;
1169 var
->red
.length
= 8;
1170 var
->green
.length
= 8;
1171 var
->blue
.length
= 8;
1172 var
->transp
.offset
= 0;
1173 var
->transp
.length
= 0;
1176 var
->red
.offset
= 16;
1177 var
->green
.offset
= 8;
1178 var
->blue
.offset
= 0;
1179 var
->red
.length
= 8;
1180 var
->green
.length
= 8;
1181 var
->blue
.length
= 8;
1182 var
->transp
.offset
= 24;
1183 var
->transp
.length
= 8;
1190 static void __fill_var(struct fb_var_screeninfo
*var
, struct fb_info
*info
,
1191 struct drm_framebuffer
*fb
)
1195 var
->xres_virtual
= fb
->width
;
1196 var
->yres_virtual
= fb
->height
;
1197 var
->accel_flags
= 0;
1198 var
->bits_per_pixel
= drm_format_info_bpp(fb
->format
, 0);
1200 var
->height
= info
->var
.height
;
1201 var
->width
= info
->var
.width
;
1203 var
->left_margin
= var
->right_margin
= 0;
1204 var
->upper_margin
= var
->lower_margin
= 0;
1205 var
->hsync_len
= var
->vsync_len
= 0;
1206 var
->sync
= var
->vmode
= 0;
1208 var
->colorspace
= 0;
1209 for (i
= 0; i
< 4; i
++)
1210 var
->reserved
[i
] = 0;
1214 * drm_fb_helper_check_var - implementation for &fb_ops.fb_check_var
1215 * @var: screeninfo to check
1216 * @info: fbdev registered by the helper
1218 int drm_fb_helper_check_var(struct fb_var_screeninfo
*var
,
1219 struct fb_info
*info
)
1221 struct drm_fb_helper
*fb_helper
= info
->par
;
1222 struct drm_framebuffer
*fb
= fb_helper
->fb
;
1223 const struct drm_format_info
*format
= fb
->format
;
1224 struct drm_device
*dev
= fb_helper
->dev
;
1227 if (in_dbg_master())
1230 if (var
->pixclock
!= 0) {
1231 drm_dbg_kms(dev
, "fbdev emulation doesn't support changing the pixel clock, value of pixclock is ignored\n");
1235 switch (format
->format
) {
1239 /* supported format with sub-byte pixels */
1243 if ((drm_format_info_block_width(format
, 0) > 1) ||
1244 (drm_format_info_block_height(format
, 0) > 1))
1250 * Changes struct fb_var_screeninfo are currently not pushed back
1251 * to KMS, hence fail if different settings are requested.
1253 bpp
= drm_format_info_bpp(format
, 0);
1254 if (var
->bits_per_pixel
> bpp
||
1255 var
->xres
> fb
->width
|| var
->yres
> fb
->height
||
1256 var
->xres_virtual
> fb
->width
|| var
->yres_virtual
> fb
->height
) {
1257 drm_dbg_kms(dev
, "fb requested width/height/bpp can't fit in current fb "
1258 "request %dx%d-%d (virtual %dx%d) > %dx%d-%d\n",
1259 var
->xres
, var
->yres
, var
->bits_per_pixel
,
1260 var
->xres_virtual
, var
->yres_virtual
,
1261 fb
->width
, fb
->height
, bpp
);
1265 __fill_var(var
, info
, fb
);
1268 * fb_pan_display() validates this, but fb_set_par() doesn't and just
1269 * falls over. Note that __fill_var above adjusts y/res_virtual.
1271 if (var
->yoffset
> var
->yres_virtual
- var
->yres
||
1272 var
->xoffset
> var
->xres_virtual
- var
->xres
)
1275 /* We neither support grayscale nor FOURCC (also stored in here). */
1276 if (var
->grayscale
> 0)
1283 * Workaround for SDL 1.2, which is known to be setting all pixel format
1284 * fields values to zero in some cases. We treat this situation as a
1285 * kind of "use some reasonable autodetected values".
1287 if (!var
->red
.offset
&& !var
->green
.offset
&&
1288 !var
->blue
.offset
&& !var
->transp
.offset
&&
1289 !var
->red
.length
&& !var
->green
.length
&&
1290 !var
->blue
.length
&& !var
->transp
.length
&&
1291 !var
->red
.msb_right
&& !var
->green
.msb_right
&&
1292 !var
->blue
.msb_right
&& !var
->transp
.msb_right
) {
1293 drm_fb_helper_fill_pixel_fmt(var
, format
);
1297 * drm fbdev emulation doesn't support changing the pixel format at all,
1298 * so reject all pixel format changing requests.
1300 if (!drm_fb_pixel_format_equal(var
, &info
->var
)) {
1301 drm_dbg_kms(dev
, "fbdev emulation doesn't support changing the pixel format\n");
1307 EXPORT_SYMBOL(drm_fb_helper_check_var
);
1310 * drm_fb_helper_set_par - implementation for &fb_ops.fb_set_par
1311 * @info: fbdev registered by the helper
1313 * This will let fbcon do the mode init and is called at initialization time by
1314 * the fbdev core when registering the driver, and later on through the hotplug
1317 int drm_fb_helper_set_par(struct fb_info
*info
)
1319 struct drm_fb_helper
*fb_helper
= info
->par
;
1320 struct fb_var_screeninfo
*var
= &info
->var
;
1323 if (oops_in_progress
)
1327 * Normally we want to make sure that a kms master takes precedence over
1328 * fbdev, to avoid fbdev flickering and occasionally stealing the
1329 * display status. But Xorg first sets the vt back to text mode using
1330 * the KDSET IOCTL with KD_TEXT, and only after that drops the master
1331 * status when exiting.
1333 * In the past this was caught by drm_fb_helper_lastclose(), but on
1334 * modern systems where logind always keeps a drm fd open to orchestrate
1335 * the vt switching, this doesn't work.
1337 * To not break the userspace ABI we have this special case here, which
1338 * is only used for the above case. Everything else uses the normal
1339 * commit function, which ensures that we never steal the display from
1340 * an active drm master.
1342 force
= var
->activate
& FB_ACTIVATE_KD_TEXT
;
1344 __drm_fb_helper_restore_fbdev_mode_unlocked(fb_helper
, force
);
1348 EXPORT_SYMBOL(drm_fb_helper_set_par
);
1350 static void pan_set(struct drm_fb_helper
*fb_helper
, int x
, int y
)
1352 struct drm_mode_set
*mode_set
;
1354 mutex_lock(&fb_helper
->client
.modeset_mutex
);
1355 drm_client_for_each_modeset(mode_set
, &fb_helper
->client
) {
1359 mutex_unlock(&fb_helper
->client
.modeset_mutex
);
1362 static int pan_display_atomic(struct fb_var_screeninfo
*var
,
1363 struct fb_info
*info
)
1365 struct drm_fb_helper
*fb_helper
= info
->par
;
1368 pan_set(fb_helper
, var
->xoffset
, var
->yoffset
);
1370 ret
= drm_client_modeset_commit_locked(&fb_helper
->client
);
1372 info
->var
.xoffset
= var
->xoffset
;
1373 info
->var
.yoffset
= var
->yoffset
;
1375 pan_set(fb_helper
, info
->var
.xoffset
, info
->var
.yoffset
);
1380 static int pan_display_legacy(struct fb_var_screeninfo
*var
,
1381 struct fb_info
*info
)
1383 struct drm_fb_helper
*fb_helper
= info
->par
;
1384 struct drm_client_dev
*client
= &fb_helper
->client
;
1385 struct drm_mode_set
*modeset
;
1388 mutex_lock(&client
->modeset_mutex
);
1389 drm_modeset_lock_all(fb_helper
->dev
);
1390 drm_client_for_each_modeset(modeset
, client
) {
1391 modeset
->x
= var
->xoffset
;
1392 modeset
->y
= var
->yoffset
;
1394 if (modeset
->num_connectors
) {
1395 ret
= drm_mode_set_config_internal(modeset
);
1397 info
->var
.xoffset
= var
->xoffset
;
1398 info
->var
.yoffset
= var
->yoffset
;
1402 drm_modeset_unlock_all(fb_helper
->dev
);
1403 mutex_unlock(&client
->modeset_mutex
);
1409 * drm_fb_helper_pan_display - implementation for &fb_ops.fb_pan_display
1410 * @var: updated screen information
1411 * @info: fbdev registered by the helper
1413 int drm_fb_helper_pan_display(struct fb_var_screeninfo
*var
,
1414 struct fb_info
*info
)
1416 struct drm_fb_helper
*fb_helper
= info
->par
;
1417 struct drm_device
*dev
= fb_helper
->dev
;
1420 if (oops_in_progress
)
1423 mutex_lock(&fb_helper
->lock
);
1424 if (!drm_master_internal_acquire(dev
)) {
1429 if (drm_drv_uses_atomic_modeset(dev
))
1430 ret
= pan_display_atomic(var
, info
);
1432 ret
= pan_display_legacy(var
, info
);
1434 drm_master_internal_release(dev
);
1436 mutex_unlock(&fb_helper
->lock
);
1440 EXPORT_SYMBOL(drm_fb_helper_pan_display
);
1442 static uint32_t drm_fb_helper_find_format(struct drm_fb_helper
*fb_helper
, const uint32_t *formats
,
1443 size_t format_count
, uint32_t bpp
, uint32_t depth
)
1445 struct drm_device
*dev
= fb_helper
->dev
;
1450 * Do not consider YUV or other complicated formats
1451 * for framebuffers. This means only legacy formats
1452 * are supported (fmt->depth is a legacy field), but
1453 * the framebuffer emulation can only deal with such
1454 * formats, specifically RGB/BGA formats.
1456 format
= drm_mode_legacy_fb_format(bpp
, depth
);
1460 for (i
= 0; i
< format_count
; ++i
) {
1461 if (formats
[i
] == format
)
1466 /* We found nothing. */
1467 drm_warn(dev
, "bpp/depth value of %u/%u not supported\n", bpp
, depth
);
1469 return DRM_FORMAT_INVALID
;
1472 static uint32_t drm_fb_helper_find_color_mode_format(struct drm_fb_helper
*fb_helper
,
1473 const uint32_t *formats
, size_t format_count
,
1474 unsigned int color_mode
)
1476 struct drm_device
*dev
= fb_helper
->dev
;
1477 uint32_t bpp
, depth
;
1479 switch (color_mode
) {
1486 bpp
= depth
= color_mode
;
1497 drm_info(dev
, "unsupported color mode of %d\n", color_mode
);
1498 return DRM_FORMAT_INVALID
;
1501 return drm_fb_helper_find_format(fb_helper
, formats
, format_count
, bpp
, depth
);
1504 static int __drm_fb_helper_find_sizes(struct drm_fb_helper
*fb_helper
,
1505 struct drm_fb_helper_surface_size
*sizes
)
1507 struct drm_client_dev
*client
= &fb_helper
->client
;
1508 struct drm_device
*dev
= fb_helper
->dev
;
1510 struct drm_connector_list_iter conn_iter
;
1511 struct drm_connector
*connector
;
1512 struct drm_mode_set
*mode_set
;
1513 uint32_t surface_format
= DRM_FORMAT_INVALID
;
1514 const struct drm_format_info
*info
;
1516 memset(sizes
, 0, sizeof(*sizes
));
1517 sizes
->fb_width
= (u32
)-1;
1518 sizes
->fb_height
= (u32
)-1;
1520 drm_client_for_each_modeset(mode_set
, client
) {
1521 struct drm_crtc
*crtc
= mode_set
->crtc
;
1522 struct drm_plane
*plane
= crtc
->primary
;
1524 drm_dbg_kms(dev
, "test CRTC %u primary plane\n", drm_crtc_index(crtc
));
1526 drm_connector_list_iter_begin(fb_helper
->dev
, &conn_iter
);
1527 drm_client_for_each_connector_iter(connector
, &conn_iter
) {
1528 struct drm_cmdline_mode
*cmdline_mode
= &connector
->cmdline_mode
;
1530 if (!cmdline_mode
->bpp_specified
)
1533 surface_format
= drm_fb_helper_find_color_mode_format(fb_helper
,
1534 plane
->format_types
,
1535 plane
->format_count
,
1537 if (surface_format
!= DRM_FORMAT_INVALID
)
1538 break; /* found supported format */
1540 drm_connector_list_iter_end(&conn_iter
);
1542 if (surface_format
!= DRM_FORMAT_INVALID
)
1543 break; /* found supported format */
1545 /* try preferred color mode */
1546 surface_format
= drm_fb_helper_find_color_mode_format(fb_helper
,
1547 plane
->format_types
,
1548 plane
->format_count
,
1549 fb_helper
->preferred_bpp
);
1550 if (surface_format
!= DRM_FORMAT_INVALID
)
1551 break; /* found supported format */
1554 if (surface_format
== DRM_FORMAT_INVALID
) {
1556 * If none of the given color modes works, fall back
1557 * to XRGB8888. Drivers are expected to provide this
1558 * format for compatibility with legacy applications.
1560 drm_warn(dev
, "No compatible format found\n");
1561 surface_format
= drm_driver_legacy_fb_format(dev
, 32, 24);
1564 info
= drm_format_info(surface_format
);
1565 sizes
->surface_bpp
= drm_format_info_bpp(info
, 0);
1566 sizes
->surface_depth
= info
->depth
;
1568 /* first up get a count of crtcs now in use and new min/maxes width/heights */
1570 drm_client_for_each_modeset(mode_set
, client
) {
1571 struct drm_display_mode
*desired_mode
;
1573 /* in case of tile group, are we the last tile vert or horiz?
1574 * If no tile group you are always the last one both vertically
1577 bool lastv
= true, lasth
= true;
1579 desired_mode
= mode_set
->mode
;
1589 sizes
->surface_width
=
1590 max_t(u32
, desired_mode
->hdisplay
+ x
, sizes
->surface_width
);
1591 sizes
->surface_height
=
1592 max_t(u32
, desired_mode
->vdisplay
+ y
, sizes
->surface_height
);
1594 for (j
= 0; j
< mode_set
->num_connectors
; j
++) {
1595 struct drm_connector
*connector
= mode_set
->connectors
[j
];
1597 if (connector
->has_tile
&&
1598 desired_mode
->hdisplay
== connector
->tile_h_size
&&
1599 desired_mode
->vdisplay
== connector
->tile_v_size
) {
1600 lasth
= (connector
->tile_h_loc
== (connector
->num_h_tile
- 1));
1601 lastv
= (connector
->tile_v_loc
== (connector
->num_v_tile
- 1));
1602 /* cloning to multiple tiles is just crazy-talk, so: */
1608 sizes
->fb_width
= min_t(u32
, desired_mode
->hdisplay
+ x
, sizes
->fb_width
);
1610 sizes
->fb_height
= min_t(u32
, desired_mode
->vdisplay
+ y
, sizes
->fb_height
);
1613 if (crtc_count
== 0 || sizes
->fb_width
== -1 || sizes
->fb_height
== -1) {
1614 drm_info(dev
, "Cannot find any crtc or sizes\n");
1621 static int drm_fb_helper_find_sizes(struct drm_fb_helper
*fb_helper
,
1622 struct drm_fb_helper_surface_size
*sizes
)
1624 struct drm_client_dev
*client
= &fb_helper
->client
;
1625 struct drm_device
*dev
= fb_helper
->dev
;
1626 struct drm_mode_config
*config
= &dev
->mode_config
;
1629 mutex_lock(&client
->modeset_mutex
);
1630 ret
= __drm_fb_helper_find_sizes(fb_helper
, sizes
);
1631 mutex_unlock(&client
->modeset_mutex
);
1636 /* Handle our overallocation */
1637 sizes
->surface_height
*= drm_fbdev_overalloc
;
1638 sizes
->surface_height
/= 100;
1639 if (sizes
->surface_height
> config
->max_height
) {
1640 drm_dbg_kms(dev
, "Fbdev over-allocation too large; clamping height to %d\n",
1641 config
->max_height
);
1642 sizes
->surface_height
= config
->max_height
;
1649 * Allocates the backing storage and sets up the fbdev info structure through
1650 * the ->fb_probe callback.
1652 static int drm_fb_helper_single_fb_probe(struct drm_fb_helper
*fb_helper
)
1654 struct drm_client_dev
*client
= &fb_helper
->client
;
1655 struct drm_device
*dev
= fb_helper
->dev
;
1656 struct drm_fb_helper_surface_size sizes
;
1659 ret
= drm_fb_helper_find_sizes(fb_helper
, &sizes
);
1661 /* First time: disable all crtc's.. */
1662 if (!fb_helper
->deferred_setup
)
1663 drm_client_modeset_commit(client
);
1667 /* push down into drivers */
1668 ret
= (*fb_helper
->funcs
->fb_probe
)(fb_helper
, &sizes
);
1672 strcpy(fb_helper
->fb
->comm
, "[fbcon]");
1674 /* Set the fb info for vgaswitcheroo clients. Does nothing otherwise. */
1675 if (dev_is_pci(dev
->dev
))
1676 vga_switcheroo_client_fb_set(to_pci_dev(dev
->dev
), fb_helper
->info
);
1681 static void drm_fb_helper_fill_fix(struct fb_info
*info
, uint32_t pitch
,
1682 bool is_color_indexed
)
1684 info
->fix
.type
= FB_TYPE_PACKED_PIXELS
;
1685 info
->fix
.visual
= is_color_indexed
? FB_VISUAL_PSEUDOCOLOR
1686 : FB_VISUAL_TRUECOLOR
;
1687 info
->fix
.mmio_start
= 0;
1688 info
->fix
.mmio_len
= 0;
1689 info
->fix
.type_aux
= 0;
1690 info
->fix
.xpanstep
= 1; /* doing it in hw */
1691 info
->fix
.ypanstep
= 1; /* doing it in hw */
1692 info
->fix
.ywrapstep
= 0;
1693 info
->fix
.accel
= FB_ACCEL_NONE
;
1695 info
->fix
.line_length
= pitch
;
1698 static void drm_fb_helper_fill_var(struct fb_info
*info
,
1699 struct drm_fb_helper
*fb_helper
,
1700 uint32_t fb_width
, uint32_t fb_height
)
1702 struct drm_framebuffer
*fb
= fb_helper
->fb
;
1703 const struct drm_format_info
*format
= fb
->format
;
1705 switch (format
->format
) {
1709 /* supported format with sub-byte pixels */
1713 WARN_ON((drm_format_info_block_width(format
, 0) > 1) ||
1714 (drm_format_info_block_height(format
, 0) > 1));
1718 info
->pseudo_palette
= fb_helper
->pseudo_palette
;
1719 info
->var
.xoffset
= 0;
1720 info
->var
.yoffset
= 0;
1721 __fill_var(&info
->var
, info
, fb
);
1722 info
->var
.activate
= FB_ACTIVATE_NOW
;
1724 drm_fb_helper_fill_pixel_fmt(&info
->var
, format
);
1726 info
->var
.xres
= fb_width
;
1727 info
->var
.yres
= fb_height
;
1731 * drm_fb_helper_fill_info - initializes fbdev information
1732 * @info: fbdev instance to set up
1733 * @fb_helper: fb helper instance to use as template
1734 * @sizes: describes fbdev size and scanout surface size
1736 * Sets up the variable and fixed fbdev metainformation from the given fb helper
1737 * instance and the drm framebuffer allocated in &drm_fb_helper.fb.
1739 * Drivers should call this (or their equivalent setup code) from their
1740 * &drm_fb_helper_funcs.fb_probe callback after having allocated the fbdev
1741 * backing storage framebuffer.
1743 void drm_fb_helper_fill_info(struct fb_info
*info
,
1744 struct drm_fb_helper
*fb_helper
,
1745 struct drm_fb_helper_surface_size
*sizes
)
1747 struct drm_framebuffer
*fb
= fb_helper
->fb
;
1749 drm_fb_helper_fill_fix(info
, fb
->pitches
[0],
1750 fb
->format
->is_color_indexed
);
1751 drm_fb_helper_fill_var(info
, fb_helper
,
1752 sizes
->fb_width
, sizes
->fb_height
);
1754 info
->par
= fb_helper
;
1756 * The DRM drivers fbdev emulation device name can be confusing if the
1757 * driver name also has a "drm" suffix on it. Leading to names such as
1758 * "simpledrmdrmfb" in /proc/fb. Unfortunately, it's an uAPI and can't
1759 * be changed due user-space tools (e.g: pm-utils) matching against it.
1761 snprintf(info
->fix
.id
, sizeof(info
->fix
.id
), "%sdrmfb",
1762 fb_helper
->dev
->driver
->name
);
1765 EXPORT_SYMBOL(drm_fb_helper_fill_info
);
1768 * This is a continuation of drm_setup_crtcs() that sets up anything related
1769 * to the framebuffer. During initialization, drm_setup_crtcs() is called before
1770 * the framebuffer has been allocated (fb_helper->fb and fb_helper->info).
1771 * So, any setup that touches those fields needs to be done here instead of in
1772 * drm_setup_crtcs().
1774 static void drm_setup_crtcs_fb(struct drm_fb_helper
*fb_helper
)
1776 struct drm_client_dev
*client
= &fb_helper
->client
;
1777 struct drm_connector_list_iter conn_iter
;
1778 struct fb_info
*info
= fb_helper
->info
;
1779 unsigned int rotation
, sw_rotations
= 0;
1780 struct drm_connector
*connector
;
1781 struct drm_mode_set
*modeset
;
1783 mutex_lock(&client
->modeset_mutex
);
1784 drm_client_for_each_modeset(modeset
, client
) {
1785 if (!modeset
->num_connectors
)
1788 modeset
->fb
= fb_helper
->fb
;
1790 if (drm_client_rotation(modeset
, &rotation
))
1791 /* Rotating in hardware, fbcon should not rotate */
1792 sw_rotations
|= DRM_MODE_ROTATE_0
;
1794 sw_rotations
|= rotation
;
1796 mutex_unlock(&client
->modeset_mutex
);
1798 drm_connector_list_iter_begin(fb_helper
->dev
, &conn_iter
);
1799 drm_client_for_each_connector_iter(connector
, &conn_iter
) {
1801 /* use first connected connector for the physical dimensions */
1802 if (connector
->status
== connector_status_connected
) {
1803 info
->var
.width
= connector
->display_info
.width_mm
;
1804 info
->var
.height
= connector
->display_info
.height_mm
;
1808 drm_connector_list_iter_end(&conn_iter
);
1810 switch (sw_rotations
) {
1811 case DRM_MODE_ROTATE_0
:
1812 info
->fbcon_rotate_hint
= FB_ROTATE_UR
;
1814 case DRM_MODE_ROTATE_90
:
1815 info
->fbcon_rotate_hint
= FB_ROTATE_CCW
;
1817 case DRM_MODE_ROTATE_180
:
1818 info
->fbcon_rotate_hint
= FB_ROTATE_UD
;
1820 case DRM_MODE_ROTATE_270
:
1821 info
->fbcon_rotate_hint
= FB_ROTATE_CW
;
1825 * Multiple bits are set / multiple rotations requested
1826 * fbcon cannot handle separate rotation settings per
1827 * output, so fallback to unrotated.
1829 info
->fbcon_rotate_hint
= FB_ROTATE_UR
;
1833 /* Note: Drops fb_helper->lock before returning. */
1835 __drm_fb_helper_initial_config_and_unlock(struct drm_fb_helper
*fb_helper
)
1837 struct drm_device
*dev
= fb_helper
->dev
;
1838 struct fb_info
*info
;
1839 unsigned int width
, height
;
1842 width
= dev
->mode_config
.max_width
;
1843 height
= dev
->mode_config
.max_height
;
1845 drm_client_modeset_probe(&fb_helper
->client
, width
, height
);
1846 ret
= drm_fb_helper_single_fb_probe(fb_helper
);
1848 if (ret
== -EAGAIN
) {
1849 fb_helper
->deferred_setup
= true;
1852 mutex_unlock(&fb_helper
->lock
);
1856 drm_setup_crtcs_fb(fb_helper
);
1858 fb_helper
->deferred_setup
= false;
1860 info
= fb_helper
->info
;
1861 info
->var
.pixclock
= 0;
1863 if (!drm_leak_fbdev_smem
)
1864 info
->flags
|= FBINFO_HIDE_SMEM_START
;
1866 /* Need to drop locks to avoid recursive deadlock in
1867 * register_framebuffer. This is ok because the only thing left to do is
1868 * register the fbdev emulation instance in kernel_fb_helper_list. */
1869 mutex_unlock(&fb_helper
->lock
);
1871 ret
= register_framebuffer(info
);
1875 drm_info(dev
, "fb%d: %s frame buffer device\n",
1876 info
->node
, info
->fix
.id
);
1878 mutex_lock(&kernel_fb_helper_lock
);
1879 if (list_empty(&kernel_fb_helper_list
))
1880 register_sysrq_key('v', &sysrq_drm_fb_helper_restore_op
);
1882 list_add(&fb_helper
->kernel_fb_list
, &kernel_fb_helper_list
);
1883 mutex_unlock(&kernel_fb_helper_lock
);
1889 * drm_fb_helper_initial_config - setup a sane initial connector configuration
1890 * @fb_helper: fb_helper device struct
1892 * Scans the CRTCs and connectors and tries to put together an initial setup.
1893 * At the moment, this is a cloned configuration across all heads with
1894 * a new framebuffer object as the backing store.
1896 * Note that this also registers the fbdev and so allows userspace to call into
1897 * the driver through the fbdev interfaces.
1899 * This function will call down into the &drm_fb_helper_funcs.fb_probe callback
1900 * to let the driver allocate and initialize the fbdev info structure and the
1901 * drm framebuffer used to back the fbdev. drm_fb_helper_fill_info() is provided
1902 * as a helper to setup simple default values for the fbdev info structure.
1906 * When you have fbcon support built-in or already loaded, this function will do
1907 * a full modeset to setup the fbdev console. Due to locking misdesign in the
1908 * VT/fbdev subsystem that entire modeset sequence has to be done while holding
1909 * console_lock. Until console_unlock is called no dmesg lines will be sent out
1910 * to consoles, not even serial console. This means when your driver crashes,
1911 * you will see absolutely nothing else but a system stuck in this function,
1912 * with no further output. Any kind of printk() you place within your own driver
1913 * or in the drm core modeset code will also never show up.
1915 * Standard debug practice is to run the fbcon setup without taking the
1916 * console_lock as a hack, to be able to see backtraces and crashes on the
1917 * serial line. This can be done by setting the fb.lockless_register_fb=1 kernel
1920 * The other option is to just disable fbdev emulation since very likely the
1921 * first modeset from userspace will crash in the same way, and is even easier
1922 * to debug. This can be done by setting the drm_kms_helper.fbdev_emulation=0
1923 * kernel cmdline option.
1926 * Zero if everything went ok, nonzero otherwise.
1928 int drm_fb_helper_initial_config(struct drm_fb_helper
*fb_helper
)
1932 if (!drm_fbdev_emulation
)
1935 mutex_lock(&fb_helper
->lock
);
1936 ret
= __drm_fb_helper_initial_config_and_unlock(fb_helper
);
1940 EXPORT_SYMBOL(drm_fb_helper_initial_config
);
1943 * drm_fb_helper_hotplug_event - respond to a hotplug notification by
1944 * probing all the outputs attached to the fb
1945 * @fb_helper: driver-allocated fbdev helper, can be NULL
1947 * Scan the connectors attached to the fb_helper and try to put together a
1948 * setup after notification of a change in output configuration.
1950 * Called at runtime, takes the mode config locks to be able to check/change the
1951 * modeset configuration. Must be run from process context (which usually means
1952 * either the output polling work or a work item launched from the driver's
1953 * hotplug interrupt).
1955 * Note that drivers may call this even before calling
1956 * drm_fb_helper_initial_config but only after drm_fb_helper_init. This allows
1957 * for a race-free fbcon setup and will make sure that the fbdev emulation will
1958 * not miss any hotplug events.
1961 * 0 on success and a non-zero error code otherwise.
1963 int drm_fb_helper_hotplug_event(struct drm_fb_helper
*fb_helper
)
1967 if (!drm_fbdev_emulation
|| !fb_helper
)
1970 mutex_lock(&fb_helper
->lock
);
1971 if (fb_helper
->deferred_setup
) {
1972 err
= __drm_fb_helper_initial_config_and_unlock(fb_helper
);
1976 if (!fb_helper
->fb
|| !drm_master_internal_acquire(fb_helper
->dev
)) {
1977 fb_helper
->delayed_hotplug
= true;
1978 mutex_unlock(&fb_helper
->lock
);
1982 drm_master_internal_release(fb_helper
->dev
);
1984 drm_dbg_kms(fb_helper
->dev
, "\n");
1986 drm_client_modeset_probe(&fb_helper
->client
, fb_helper
->fb
->width
, fb_helper
->fb
->height
);
1987 drm_setup_crtcs_fb(fb_helper
);
1988 mutex_unlock(&fb_helper
->lock
);
1990 drm_fb_helper_set_par(fb_helper
->info
);
1994 EXPORT_SYMBOL(drm_fb_helper_hotplug_event
);
1997 * drm_fb_helper_lastclose - DRM driver lastclose helper for fbdev emulation
2000 * This function can be used as the &drm_driver->lastclose callback for drivers
2001 * that only need to call drm_fb_helper_restore_fbdev_mode_unlocked().
2003 void drm_fb_helper_lastclose(struct drm_device
*dev
)
2005 drm_fb_helper_restore_fbdev_mode_unlocked(dev
->fb_helper
);
2007 EXPORT_SYMBOL(drm_fb_helper_lastclose
);
2010 * drm_fb_helper_output_poll_changed - DRM mode config \.output_poll_changed
2011 * helper for fbdev emulation
2014 * This function can be used as the
2015 * &drm_mode_config_funcs.output_poll_changed callback for drivers that only
2016 * need to call drm_fbdev.hotplug_event().
2018 void drm_fb_helper_output_poll_changed(struct drm_device
*dev
)
2020 drm_fb_helper_hotplug_event(dev
->fb_helper
);
2022 EXPORT_SYMBOL(drm_fb_helper_output_poll_changed
);