cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

drm_fb_helper.c (74297B)


      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#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
     31
     32#include <linux/console.h>
     33#include <linux/dma-buf.h>
     34#include <linux/kernel.h>
     35#include <linux/module.h>
     36#include <linux/slab.h>
     37#include <linux/sysrq.h>
     38#include <linux/vmalloc.h>
     39
     40#include <drm/drm_atomic.h>
     41#include <drm/drm_crtc.h>
     42#include <drm/drm_crtc_helper.h>
     43#include <drm/drm_drv.h>
     44#include <drm/drm_fb_helper.h>
     45#include <drm/drm_fourcc.h>
     46#include <drm/drm_print.h>
     47#include <drm/drm_vblank.h>
     48
     49#include "drm_crtc_helper_internal.h"
     50#include "drm_internal.h"
     51
     52static bool drm_fbdev_emulation = true;
     53module_param_named(fbdev_emulation, drm_fbdev_emulation, bool, 0600);
     54MODULE_PARM_DESC(fbdev_emulation,
     55		 "Enable legacy fbdev emulation [default=true]");
     56
     57static int drm_fbdev_overalloc = CONFIG_DRM_FBDEV_OVERALLOC;
     58module_param(drm_fbdev_overalloc, int, 0444);
     59MODULE_PARM_DESC(drm_fbdev_overalloc,
     60		 "Overallocation of the fbdev buffer (%) [default="
     61		 __MODULE_STRING(CONFIG_DRM_FBDEV_OVERALLOC) "]");
     62
     63/*
     64 * In order to keep user-space compatibility, we want in certain use-cases
     65 * to keep leaking the fbdev physical address to the user-space program
     66 * handling the fbdev buffer.
     67 * This is a bad habit essentially kept into closed source opengl driver
     68 * that should really be moved into open-source upstream projects instead
     69 * of using legacy physical addresses in user space to communicate with
     70 * other out-of-tree kernel modules.
     71 *
     72 * This module_param *should* be removed as soon as possible and be
     73 * considered as a broken and legacy behaviour from a modern fbdev device.
     74 */
     75#if IS_ENABLED(CONFIG_DRM_FBDEV_LEAK_PHYS_SMEM)
     76static bool drm_leak_fbdev_smem = false;
     77module_param_unsafe(drm_leak_fbdev_smem, bool, 0600);
     78MODULE_PARM_DESC(drm_leak_fbdev_smem,
     79		 "Allow unsafe leaking fbdev physical smem address [default=false]");
     80#endif
     81
     82static LIST_HEAD(kernel_fb_helper_list);
     83static DEFINE_MUTEX(kernel_fb_helper_lock);
     84
     85/**
     86 * DOC: fbdev helpers
     87 *
     88 * The fb helper functions are useful to provide an fbdev on top of a drm kernel
     89 * mode setting driver. They can be used mostly independently from the crtc
     90 * helper functions used by many drivers to implement the kernel mode setting
     91 * interfaces.
     92 *
     93 * Drivers that support a dumb buffer with a virtual address and mmap support,
     94 * should try out the generic fbdev emulation using drm_fbdev_generic_setup().
     95 * It will automatically set up deferred I/O if the driver requires a shadow
     96 * buffer.
     97 *
     98 * At runtime drivers should restore the fbdev console by using
     99 * drm_fb_helper_lastclose() as their &drm_driver.lastclose callback.
    100 * They should also notify the fb helper code from updates to the output
    101 * configuration by using drm_fb_helper_output_poll_changed() as their
    102 * &drm_mode_config_funcs.output_poll_changed callback.
    103 *
    104 * For suspend/resume consider using drm_mode_config_helper_suspend() and
    105 * drm_mode_config_helper_resume() which takes care of fbdev as well.
    106 *
    107 * All other functions exported by the fb helper library can be used to
    108 * implement the fbdev driver interface by the driver.
    109 *
    110 * It is possible, though perhaps somewhat tricky, to implement race-free
    111 * hotplug detection using the fbdev helpers. The drm_fb_helper_prepare()
    112 * helper must be called first to initialize the minimum required to make
    113 * hotplug detection work. Drivers also need to make sure to properly set up
    114 * the &drm_mode_config.funcs member. After calling drm_kms_helper_poll_init()
    115 * it is safe to enable interrupts and start processing hotplug events. At the
    116 * same time, drivers should initialize all modeset objects such as CRTCs,
    117 * encoders and connectors. To finish up the fbdev helper initialization, the
    118 * drm_fb_helper_init() function is called. To probe for all attached displays
    119 * and set up an initial configuration using the detected hardware, drivers
    120 * should call drm_fb_helper_initial_config().
    121 *
    122 * If &drm_framebuffer_funcs.dirty is set, the
    123 * drm_fb_helper_{cfb,sys}_{write,fillrect,copyarea,imageblit} functions will
    124 * accumulate changes and schedule &drm_fb_helper.dirty_work to run right
    125 * away. This worker then calls the dirty() function ensuring that it will
    126 * always run in process context since the fb_*() function could be running in
    127 * atomic context. If drm_fb_helper_deferred_io() is used as the deferred_io
    128 * callback it will also schedule dirty_work with the damage collected from the
    129 * mmap page writes.
    130 *
    131 * Deferred I/O is not compatible with SHMEM. Such drivers should request an
    132 * fbdev shadow buffer and call drm_fbdev_generic_setup() instead.
    133 */
    134
    135static void drm_fb_helper_restore_lut_atomic(struct drm_crtc *crtc)
    136{
    137	uint16_t *r_base, *g_base, *b_base;
    138
    139	if (crtc->funcs->gamma_set == NULL)
    140		return;
    141
    142	r_base = crtc->gamma_store;
    143	g_base = r_base + crtc->gamma_size;
    144	b_base = g_base + crtc->gamma_size;
    145
    146	crtc->funcs->gamma_set(crtc, r_base, g_base, b_base,
    147			       crtc->gamma_size, NULL);
    148}
    149
    150/**
    151 * drm_fb_helper_debug_enter - implementation for &fb_ops.fb_debug_enter
    152 * @info: fbdev registered by the helper
    153 */
    154int drm_fb_helper_debug_enter(struct fb_info *info)
    155{
    156	struct drm_fb_helper *helper = info->par;
    157	const struct drm_crtc_helper_funcs *funcs;
    158	struct drm_mode_set *mode_set;
    159
    160	list_for_each_entry(helper, &kernel_fb_helper_list, kernel_fb_list) {
    161		mutex_lock(&helper->client.modeset_mutex);
    162		drm_client_for_each_modeset(mode_set, &helper->client) {
    163			if (!mode_set->crtc->enabled)
    164				continue;
    165
    166			funcs =	mode_set->crtc->helper_private;
    167			if (funcs->mode_set_base_atomic == NULL)
    168				continue;
    169
    170			if (drm_drv_uses_atomic_modeset(mode_set->crtc->dev))
    171				continue;
    172
    173			funcs->mode_set_base_atomic(mode_set->crtc,
    174						    mode_set->fb,
    175						    mode_set->x,
    176						    mode_set->y,
    177						    ENTER_ATOMIC_MODE_SET);
    178		}
    179		mutex_unlock(&helper->client.modeset_mutex);
    180	}
    181
    182	return 0;
    183}
    184EXPORT_SYMBOL(drm_fb_helper_debug_enter);
    185
    186/**
    187 * drm_fb_helper_debug_leave - implementation for &fb_ops.fb_debug_leave
    188 * @info: fbdev registered by the helper
    189 */
    190int drm_fb_helper_debug_leave(struct fb_info *info)
    191{
    192	struct drm_fb_helper *helper = info->par;
    193	struct drm_client_dev *client = &helper->client;
    194	struct drm_device *dev = helper->dev;
    195	struct drm_crtc *crtc;
    196	const struct drm_crtc_helper_funcs *funcs;
    197	struct drm_mode_set *mode_set;
    198	struct drm_framebuffer *fb;
    199
    200	mutex_lock(&client->modeset_mutex);
    201	drm_client_for_each_modeset(mode_set, client) {
    202		crtc = mode_set->crtc;
    203		if (drm_drv_uses_atomic_modeset(crtc->dev))
    204			continue;
    205
    206		funcs = crtc->helper_private;
    207		fb = crtc->primary->fb;
    208
    209		if (!crtc->enabled)
    210			continue;
    211
    212		if (!fb) {
    213			drm_err(dev, "no fb to restore?\n");
    214			continue;
    215		}
    216
    217		if (funcs->mode_set_base_atomic == NULL)
    218			continue;
    219
    220		drm_fb_helper_restore_lut_atomic(mode_set->crtc);
    221		funcs->mode_set_base_atomic(mode_set->crtc, fb, crtc->x,
    222					    crtc->y, LEAVE_ATOMIC_MODE_SET);
    223	}
    224	mutex_unlock(&client->modeset_mutex);
    225
    226	return 0;
    227}
    228EXPORT_SYMBOL(drm_fb_helper_debug_leave);
    229
    230static int
    231__drm_fb_helper_restore_fbdev_mode_unlocked(struct drm_fb_helper *fb_helper,
    232					    bool force)
    233{
    234	bool do_delayed;
    235	int ret;
    236
    237	if (!drm_fbdev_emulation || !fb_helper)
    238		return -ENODEV;
    239
    240	if (READ_ONCE(fb_helper->deferred_setup))
    241		return 0;
    242
    243	mutex_lock(&fb_helper->lock);
    244	if (force) {
    245		/*
    246		 * Yes this is the _locked version which expects the master lock
    247		 * to be held. But for forced restores we're intentionally
    248		 * racing here, see drm_fb_helper_set_par().
    249		 */
    250		ret = drm_client_modeset_commit_locked(&fb_helper->client);
    251	} else {
    252		ret = drm_client_modeset_commit(&fb_helper->client);
    253	}
    254
    255	do_delayed = fb_helper->delayed_hotplug;
    256	if (do_delayed)
    257		fb_helper->delayed_hotplug = false;
    258	mutex_unlock(&fb_helper->lock);
    259
    260	if (do_delayed)
    261		drm_fb_helper_hotplug_event(fb_helper);
    262
    263	return ret;
    264}
    265
    266/**
    267 * drm_fb_helper_restore_fbdev_mode_unlocked - restore fbdev configuration
    268 * @fb_helper: driver-allocated fbdev helper, can be NULL
    269 *
    270 * This should be called from driver's drm &drm_driver.lastclose callback
    271 * when implementing an fbcon on top of kms using this helper. This ensures that
    272 * the user isn't greeted with a black screen when e.g. X dies.
    273 *
    274 * RETURNS:
    275 * Zero if everything went ok, negative error code otherwise.
    276 */
    277int drm_fb_helper_restore_fbdev_mode_unlocked(struct drm_fb_helper *fb_helper)
    278{
    279	return __drm_fb_helper_restore_fbdev_mode_unlocked(fb_helper, false);
    280}
    281EXPORT_SYMBOL(drm_fb_helper_restore_fbdev_mode_unlocked);
    282
    283#ifdef CONFIG_MAGIC_SYSRQ
    284/* emergency restore, don't bother with error reporting */
    285static void drm_fb_helper_restore_work_fn(struct work_struct *ignored)
    286{
    287	struct drm_fb_helper *helper;
    288
    289	mutex_lock(&kernel_fb_helper_lock);
    290	list_for_each_entry(helper, &kernel_fb_helper_list, kernel_fb_list) {
    291		struct drm_device *dev = helper->dev;
    292
    293		if (dev->switch_power_state == DRM_SWITCH_POWER_OFF)
    294			continue;
    295
    296		mutex_lock(&helper->lock);
    297		drm_client_modeset_commit_locked(&helper->client);
    298		mutex_unlock(&helper->lock);
    299	}
    300	mutex_unlock(&kernel_fb_helper_lock);
    301}
    302
    303static DECLARE_WORK(drm_fb_helper_restore_work, drm_fb_helper_restore_work_fn);
    304
    305static void drm_fb_helper_sysrq(int dummy1)
    306{
    307	schedule_work(&drm_fb_helper_restore_work);
    308}
    309
    310static const struct sysrq_key_op sysrq_drm_fb_helper_restore_op = {
    311	.handler = drm_fb_helper_sysrq,
    312	.help_msg = "force-fb(v)",
    313	.action_msg = "Restore framebuffer console",
    314};
    315#else
    316static const struct sysrq_key_op sysrq_drm_fb_helper_restore_op = { };
    317#endif
    318
    319static void drm_fb_helper_dpms(struct fb_info *info, int dpms_mode)
    320{
    321	struct drm_fb_helper *fb_helper = info->par;
    322
    323	mutex_lock(&fb_helper->lock);
    324	drm_client_modeset_dpms(&fb_helper->client, dpms_mode);
    325	mutex_unlock(&fb_helper->lock);
    326}
    327
    328/**
    329 * drm_fb_helper_blank - implementation for &fb_ops.fb_blank
    330 * @blank: desired blanking state
    331 * @info: fbdev registered by the helper
    332 */
    333int drm_fb_helper_blank(int blank, struct fb_info *info)
    334{
    335	if (oops_in_progress)
    336		return -EBUSY;
    337
    338	switch (blank) {
    339	/* Display: On; HSync: On, VSync: On */
    340	case FB_BLANK_UNBLANK:
    341		drm_fb_helper_dpms(info, DRM_MODE_DPMS_ON);
    342		break;
    343	/* Display: Off; HSync: On, VSync: On */
    344	case FB_BLANK_NORMAL:
    345		drm_fb_helper_dpms(info, DRM_MODE_DPMS_STANDBY);
    346		break;
    347	/* Display: Off; HSync: Off, VSync: On */
    348	case FB_BLANK_HSYNC_SUSPEND:
    349		drm_fb_helper_dpms(info, DRM_MODE_DPMS_STANDBY);
    350		break;
    351	/* Display: Off; HSync: On, VSync: Off */
    352	case FB_BLANK_VSYNC_SUSPEND:
    353		drm_fb_helper_dpms(info, DRM_MODE_DPMS_SUSPEND);
    354		break;
    355	/* Display: Off; HSync: Off, VSync: Off */
    356	case FB_BLANK_POWERDOWN:
    357		drm_fb_helper_dpms(info, DRM_MODE_DPMS_OFF);
    358		break;
    359	}
    360	return 0;
    361}
    362EXPORT_SYMBOL(drm_fb_helper_blank);
    363
    364static void drm_fb_helper_resume_worker(struct work_struct *work)
    365{
    366	struct drm_fb_helper *helper = container_of(work, struct drm_fb_helper,
    367						    resume_work);
    368
    369	console_lock();
    370	fb_set_suspend(helper->fbdev, 0);
    371	console_unlock();
    372}
    373
    374static void drm_fb_helper_damage_blit_real(struct drm_fb_helper *fb_helper,
    375					   struct drm_clip_rect *clip,
    376					   struct iosys_map *dst)
    377{
    378	struct drm_framebuffer *fb = fb_helper->fb;
    379	unsigned int cpp = fb->format->cpp[0];
    380	size_t offset = clip->y1 * fb->pitches[0] + clip->x1 * cpp;
    381	void *src = fb_helper->fbdev->screen_buffer + offset;
    382	size_t len = (clip->x2 - clip->x1) * cpp;
    383	unsigned int y;
    384
    385	iosys_map_incr(dst, offset); /* go to first pixel within clip rect */
    386
    387	for (y = clip->y1; y < clip->y2; y++) {
    388		iosys_map_memcpy_to(dst, 0, src, len);
    389		iosys_map_incr(dst, fb->pitches[0]);
    390		src += fb->pitches[0];
    391	}
    392}
    393
    394static int drm_fb_helper_damage_blit(struct drm_fb_helper *fb_helper,
    395				     struct drm_clip_rect *clip)
    396{
    397	struct drm_client_buffer *buffer = fb_helper->buffer;
    398	struct iosys_map map, dst;
    399	int ret;
    400
    401	/*
    402	 * We have to pin the client buffer to its current location while
    403	 * flushing the shadow buffer. In the general case, concurrent
    404	 * modesetting operations could try to move the buffer and would
    405	 * fail. The modeset has to be serialized by acquiring the reservation
    406	 * object of the underlying BO here.
    407	 *
    408	 * For fbdev emulation, we only have to protect against fbdev modeset
    409	 * operations. Nothing else will involve the client buffer's BO. So it
    410	 * is sufficient to acquire struct drm_fb_helper.lock here.
    411	 */
    412	mutex_lock(&fb_helper->lock);
    413
    414	ret = drm_client_buffer_vmap(buffer, &map);
    415	if (ret)
    416		goto out;
    417
    418	dst = map;
    419	drm_fb_helper_damage_blit_real(fb_helper, clip, &dst);
    420
    421	drm_client_buffer_vunmap(buffer);
    422
    423out:
    424	mutex_unlock(&fb_helper->lock);
    425
    426	return ret;
    427}
    428
    429static void drm_fb_helper_damage_work(struct work_struct *work)
    430{
    431	struct drm_fb_helper *helper = container_of(work, struct drm_fb_helper,
    432						    damage_work);
    433	struct drm_device *dev = helper->dev;
    434	struct drm_clip_rect *clip = &helper->damage_clip;
    435	struct drm_clip_rect clip_copy;
    436	unsigned long flags;
    437	int ret;
    438
    439	spin_lock_irqsave(&helper->damage_lock, flags);
    440	clip_copy = *clip;
    441	clip->x1 = clip->y1 = ~0;
    442	clip->x2 = clip->y2 = 0;
    443	spin_unlock_irqrestore(&helper->damage_lock, flags);
    444
    445	/* Call damage handlers only if necessary */
    446	if (!(clip_copy.x1 < clip_copy.x2 && clip_copy.y1 < clip_copy.y2))
    447		return;
    448
    449	if (helper->buffer) {
    450		ret = drm_fb_helper_damage_blit(helper, &clip_copy);
    451		if (drm_WARN_ONCE(dev, ret, "Damage blitter failed: ret=%d\n", ret))
    452			goto err;
    453	}
    454
    455	if (helper->fb->funcs->dirty) {
    456		ret = helper->fb->funcs->dirty(helper->fb, NULL, 0, 0, &clip_copy, 1);
    457		if (drm_WARN_ONCE(dev, ret, "Dirty helper failed: ret=%d\n", ret))
    458			goto err;
    459	}
    460
    461	return;
    462
    463err:
    464	/*
    465	 * Restore damage clip rectangle on errors. The next run
    466	 * of the damage worker will perform the update.
    467	 */
    468	spin_lock_irqsave(&helper->damage_lock, flags);
    469	clip->x1 = min_t(u32, clip->x1, clip_copy.x1);
    470	clip->y1 = min_t(u32, clip->y1, clip_copy.y1);
    471	clip->x2 = max_t(u32, clip->x2, clip_copy.x2);
    472	clip->y2 = max_t(u32, clip->y2, clip_copy.y2);
    473	spin_unlock_irqrestore(&helper->damage_lock, flags);
    474}
    475
    476/**
    477 * drm_fb_helper_prepare - setup a drm_fb_helper structure
    478 * @dev: DRM device
    479 * @helper: driver-allocated fbdev helper structure to set up
    480 * @funcs: pointer to structure of functions associate with this helper
    481 *
    482 * Sets up the bare minimum to make the framebuffer helper usable. This is
    483 * useful to implement race-free initialization of the polling helpers.
    484 */
    485void drm_fb_helper_prepare(struct drm_device *dev, struct drm_fb_helper *helper,
    486			   const struct drm_fb_helper_funcs *funcs)
    487{
    488	INIT_LIST_HEAD(&helper->kernel_fb_list);
    489	spin_lock_init(&helper->damage_lock);
    490	INIT_WORK(&helper->resume_work, drm_fb_helper_resume_worker);
    491	INIT_WORK(&helper->damage_work, drm_fb_helper_damage_work);
    492	helper->damage_clip.x1 = helper->damage_clip.y1 = ~0;
    493	mutex_init(&helper->lock);
    494	helper->funcs = funcs;
    495	helper->dev = dev;
    496}
    497EXPORT_SYMBOL(drm_fb_helper_prepare);
    498
    499/**
    500 * drm_fb_helper_init - initialize a &struct drm_fb_helper
    501 * @dev: drm device
    502 * @fb_helper: driver-allocated fbdev helper structure to initialize
    503 *
    504 * This allocates the structures for the fbdev helper with the given limits.
    505 * Note that this won't yet touch the hardware (through the driver interfaces)
    506 * nor register the fbdev. This is only done in drm_fb_helper_initial_config()
    507 * to allow driver writes more control over the exact init sequence.
    508 *
    509 * Drivers must call drm_fb_helper_prepare() before calling this function.
    510 *
    511 * RETURNS:
    512 * Zero if everything went ok, nonzero otherwise.
    513 */
    514int drm_fb_helper_init(struct drm_device *dev,
    515		       struct drm_fb_helper *fb_helper)
    516{
    517	int ret;
    518
    519	if (!drm_fbdev_emulation) {
    520		dev->fb_helper = fb_helper;
    521		return 0;
    522	}
    523
    524	/*
    525	 * If this is not the generic fbdev client, initialize a drm_client
    526	 * without callbacks so we can use the modesets.
    527	 */
    528	if (!fb_helper->client.funcs) {
    529		ret = drm_client_init(dev, &fb_helper->client, "drm_fb_helper", NULL);
    530		if (ret)
    531			return ret;
    532	}
    533
    534	dev->fb_helper = fb_helper;
    535
    536	return 0;
    537}
    538EXPORT_SYMBOL(drm_fb_helper_init);
    539
    540/**
    541 * drm_fb_helper_alloc_fbi - allocate fb_info and some of its members
    542 * @fb_helper: driver-allocated fbdev helper
    543 *
    544 * A helper to alloc fb_info and the members cmap and apertures. Called
    545 * by the driver within the fb_probe fb_helper callback function. Drivers do not
    546 * need to release the allocated fb_info structure themselves, this is
    547 * automatically done when calling drm_fb_helper_fini().
    548 *
    549 * RETURNS:
    550 * fb_info pointer if things went okay, pointer containing error code
    551 * otherwise
    552 */
    553struct fb_info *drm_fb_helper_alloc_fbi(struct drm_fb_helper *fb_helper)
    554{
    555	struct device *dev = fb_helper->dev->dev;
    556	struct fb_info *info;
    557	int ret;
    558
    559	info = framebuffer_alloc(0, dev);
    560	if (!info)
    561		return ERR_PTR(-ENOMEM);
    562
    563	ret = fb_alloc_cmap(&info->cmap, 256, 0);
    564	if (ret)
    565		goto err_release;
    566
    567	/*
    568	 * TODO: We really should be smarter here and alloc an aperture
    569	 * for each IORESOURCE_MEM resource helper->dev->dev has and also
    570	 * init the ranges of the appertures based on the resources.
    571	 * Note some drivers currently count on there being only 1 empty
    572	 * aperture and fill this themselves, these will need to be dealt
    573	 * with somehow when fixing this.
    574	 */
    575	info->apertures = alloc_apertures(1);
    576	if (!info->apertures) {
    577		ret = -ENOMEM;
    578		goto err_free_cmap;
    579	}
    580
    581	fb_helper->fbdev = info;
    582	info->skip_vt_switch = true;
    583
    584	return info;
    585
    586err_free_cmap:
    587	fb_dealloc_cmap(&info->cmap);
    588err_release:
    589	framebuffer_release(info);
    590	return ERR_PTR(ret);
    591}
    592EXPORT_SYMBOL(drm_fb_helper_alloc_fbi);
    593
    594/**
    595 * drm_fb_helper_unregister_fbi - unregister fb_info framebuffer device
    596 * @fb_helper: driver-allocated fbdev helper, can be NULL
    597 *
    598 * A wrapper around unregister_framebuffer, to release the fb_info
    599 * framebuffer device. This must be called before releasing all resources for
    600 * @fb_helper by calling drm_fb_helper_fini().
    601 */
    602void drm_fb_helper_unregister_fbi(struct drm_fb_helper *fb_helper)
    603{
    604	if (fb_helper && fb_helper->fbdev)
    605		unregister_framebuffer(fb_helper->fbdev);
    606}
    607EXPORT_SYMBOL(drm_fb_helper_unregister_fbi);
    608
    609/**
    610 * drm_fb_helper_fini - finialize a &struct drm_fb_helper
    611 * @fb_helper: driver-allocated fbdev helper, can be NULL
    612 *
    613 * This cleans up all remaining resources associated with @fb_helper.
    614 */
    615void drm_fb_helper_fini(struct drm_fb_helper *fb_helper)
    616{
    617	struct fb_info *info;
    618
    619	if (!fb_helper)
    620		return;
    621
    622	fb_helper->dev->fb_helper = NULL;
    623
    624	if (!drm_fbdev_emulation)
    625		return;
    626
    627	cancel_work_sync(&fb_helper->resume_work);
    628	cancel_work_sync(&fb_helper->damage_work);
    629
    630	info = fb_helper->fbdev;
    631	if (info) {
    632		if (info->cmap.len)
    633			fb_dealloc_cmap(&info->cmap);
    634		framebuffer_release(info);
    635	}
    636	fb_helper->fbdev = NULL;
    637
    638	mutex_lock(&kernel_fb_helper_lock);
    639	if (!list_empty(&fb_helper->kernel_fb_list)) {
    640		list_del(&fb_helper->kernel_fb_list);
    641		if (list_empty(&kernel_fb_helper_list))
    642			unregister_sysrq_key('v', &sysrq_drm_fb_helper_restore_op);
    643	}
    644	mutex_unlock(&kernel_fb_helper_lock);
    645
    646	mutex_destroy(&fb_helper->lock);
    647
    648	if (!fb_helper->client.funcs)
    649		drm_client_release(&fb_helper->client);
    650}
    651EXPORT_SYMBOL(drm_fb_helper_fini);
    652
    653static bool drm_fbdev_use_shadow_fb(struct drm_fb_helper *fb_helper)
    654{
    655	struct drm_device *dev = fb_helper->dev;
    656	struct drm_framebuffer *fb = fb_helper->fb;
    657
    658	return dev->mode_config.prefer_shadow_fbdev ||
    659	       dev->mode_config.prefer_shadow ||
    660	       fb->funcs->dirty;
    661}
    662
    663static void drm_fb_helper_damage(struct fb_info *info, u32 x, u32 y,
    664				 u32 width, u32 height)
    665{
    666	struct drm_fb_helper *helper = info->par;
    667	struct drm_clip_rect *clip = &helper->damage_clip;
    668	unsigned long flags;
    669
    670	if (!drm_fbdev_use_shadow_fb(helper))
    671		return;
    672
    673	spin_lock_irqsave(&helper->damage_lock, flags);
    674	clip->x1 = min_t(u32, clip->x1, x);
    675	clip->y1 = min_t(u32, clip->y1, y);
    676	clip->x2 = max_t(u32, clip->x2, x + width);
    677	clip->y2 = max_t(u32, clip->y2, y + height);
    678	spin_unlock_irqrestore(&helper->damage_lock, flags);
    679
    680	schedule_work(&helper->damage_work);
    681}
    682
    683/* Convert memory region into area of scanlines and pixels per scanline */
    684static void drm_fb_helper_memory_range_to_clip(struct fb_info *info, off_t off, size_t len,
    685					       struct drm_rect *clip)
    686{
    687	off_t end = off + len;
    688	u32 x1 = 0;
    689	u32 y1 = off / info->fix.line_length;
    690	u32 x2 = info->var.xres;
    691	u32 y2 = DIV_ROUND_UP(end, info->fix.line_length);
    692
    693	if ((y2 - y1) == 1) {
    694		/*
    695		 * We've only written to a single scanline. Try to reduce
    696		 * the number of horizontal pixels that need an update.
    697		 */
    698		off_t bit_off = (off % info->fix.line_length) * 8;
    699		off_t bit_end = (end % info->fix.line_length) * 8;
    700
    701		x1 = bit_off / info->var.bits_per_pixel;
    702		x2 = DIV_ROUND_UP(bit_end, info->var.bits_per_pixel);
    703	}
    704
    705	drm_rect_init(clip, x1, y1, x2 - x1, y2 - y1);
    706}
    707
    708/**
    709 * drm_fb_helper_deferred_io() - fbdev deferred_io callback function
    710 * @info: fb_info struct pointer
    711 * @pagereflist: list of mmap framebuffer pages that have to be flushed
    712 *
    713 * This function is used as the &fb_deferred_io.deferred_io
    714 * callback function for flushing the fbdev mmap writes.
    715 */
    716void drm_fb_helper_deferred_io(struct fb_info *info, struct list_head *pagereflist)
    717{
    718	unsigned long start, end, min, max;
    719	struct fb_deferred_io_pageref *pageref;
    720	struct drm_rect damage_area;
    721
    722	min = ULONG_MAX;
    723	max = 0;
    724	list_for_each_entry(pageref, pagereflist, list) {
    725		start = pageref->offset;
    726		end = start + PAGE_SIZE;
    727		min = min(min, start);
    728		max = max(max, end);
    729	}
    730	if (min >= max)
    731		return;
    732
    733	drm_fb_helper_memory_range_to_clip(info, min, max - min, &damage_area);
    734	drm_fb_helper_damage(info, damage_area.x1, damage_area.y1,
    735			     drm_rect_width(&damage_area),
    736			     drm_rect_height(&damage_area));
    737}
    738EXPORT_SYMBOL(drm_fb_helper_deferred_io);
    739
    740/**
    741 * drm_fb_helper_sys_read - wrapper around fb_sys_read
    742 * @info: fb_info struct pointer
    743 * @buf: userspace buffer to read from framebuffer memory
    744 * @count: number of bytes to read from framebuffer memory
    745 * @ppos: read offset within framebuffer memory
    746 *
    747 * A wrapper around fb_sys_read implemented by fbdev core
    748 */
    749ssize_t drm_fb_helper_sys_read(struct fb_info *info, char __user *buf,
    750			       size_t count, loff_t *ppos)
    751{
    752	return fb_sys_read(info, buf, count, ppos);
    753}
    754EXPORT_SYMBOL(drm_fb_helper_sys_read);
    755
    756/**
    757 * drm_fb_helper_sys_write - wrapper around fb_sys_write
    758 * @info: fb_info struct pointer
    759 * @buf: userspace buffer to write to framebuffer memory
    760 * @count: number of bytes to write to framebuffer memory
    761 * @ppos: write offset within framebuffer memory
    762 *
    763 * A wrapper around fb_sys_write implemented by fbdev core
    764 */
    765ssize_t drm_fb_helper_sys_write(struct fb_info *info, const char __user *buf,
    766				size_t count, loff_t *ppos)
    767{
    768	loff_t pos = *ppos;
    769	ssize_t ret;
    770	struct drm_rect damage_area;
    771
    772	ret = fb_sys_write(info, buf, count, ppos);
    773	if (ret <= 0)
    774		return ret;
    775
    776	drm_fb_helper_memory_range_to_clip(info, pos, ret, &damage_area);
    777	drm_fb_helper_damage(info, damage_area.x1, damage_area.y1,
    778			     drm_rect_width(&damage_area),
    779			     drm_rect_height(&damage_area));
    780
    781	return ret;
    782}
    783EXPORT_SYMBOL(drm_fb_helper_sys_write);
    784
    785/**
    786 * drm_fb_helper_sys_fillrect - wrapper around sys_fillrect
    787 * @info: fbdev registered by the helper
    788 * @rect: info about rectangle to fill
    789 *
    790 * A wrapper around sys_fillrect implemented by fbdev core
    791 */
    792void drm_fb_helper_sys_fillrect(struct fb_info *info,
    793				const struct fb_fillrect *rect)
    794{
    795	sys_fillrect(info, rect);
    796	drm_fb_helper_damage(info, rect->dx, rect->dy, rect->width, rect->height);
    797}
    798EXPORT_SYMBOL(drm_fb_helper_sys_fillrect);
    799
    800/**
    801 * drm_fb_helper_sys_copyarea - wrapper around sys_copyarea
    802 * @info: fbdev registered by the helper
    803 * @area: info about area to copy
    804 *
    805 * A wrapper around sys_copyarea implemented by fbdev core
    806 */
    807void drm_fb_helper_sys_copyarea(struct fb_info *info,
    808				const struct fb_copyarea *area)
    809{
    810	sys_copyarea(info, area);
    811	drm_fb_helper_damage(info, area->dx, area->dy, area->width, area->height);
    812}
    813EXPORT_SYMBOL(drm_fb_helper_sys_copyarea);
    814
    815/**
    816 * drm_fb_helper_sys_imageblit - wrapper around sys_imageblit
    817 * @info: fbdev registered by the helper
    818 * @image: info about image to blit
    819 *
    820 * A wrapper around sys_imageblit implemented by fbdev core
    821 */
    822void drm_fb_helper_sys_imageblit(struct fb_info *info,
    823				 const struct fb_image *image)
    824{
    825	sys_imageblit(info, image);
    826	drm_fb_helper_damage(info, image->dx, image->dy, image->width, image->height);
    827}
    828EXPORT_SYMBOL(drm_fb_helper_sys_imageblit);
    829
    830/**
    831 * drm_fb_helper_cfb_fillrect - wrapper around cfb_fillrect
    832 * @info: fbdev registered by the helper
    833 * @rect: info about rectangle to fill
    834 *
    835 * A wrapper around cfb_fillrect implemented by fbdev core
    836 */
    837void drm_fb_helper_cfb_fillrect(struct fb_info *info,
    838				const struct fb_fillrect *rect)
    839{
    840	cfb_fillrect(info, rect);
    841	drm_fb_helper_damage(info, rect->dx, rect->dy, rect->width, rect->height);
    842}
    843EXPORT_SYMBOL(drm_fb_helper_cfb_fillrect);
    844
    845/**
    846 * drm_fb_helper_cfb_copyarea - wrapper around cfb_copyarea
    847 * @info: fbdev registered by the helper
    848 * @area: info about area to copy
    849 *
    850 * A wrapper around cfb_copyarea implemented by fbdev core
    851 */
    852void drm_fb_helper_cfb_copyarea(struct fb_info *info,
    853				const struct fb_copyarea *area)
    854{
    855	cfb_copyarea(info, area);
    856	drm_fb_helper_damage(info, area->dx, area->dy, area->width, area->height);
    857}
    858EXPORT_SYMBOL(drm_fb_helper_cfb_copyarea);
    859
    860/**
    861 * drm_fb_helper_cfb_imageblit - wrapper around cfb_imageblit
    862 * @info: fbdev registered by the helper
    863 * @image: info about image to blit
    864 *
    865 * A wrapper around cfb_imageblit implemented by fbdev core
    866 */
    867void drm_fb_helper_cfb_imageblit(struct fb_info *info,
    868				 const struct fb_image *image)
    869{
    870	cfb_imageblit(info, image);
    871	drm_fb_helper_damage(info, image->dx, image->dy, image->width, image->height);
    872}
    873EXPORT_SYMBOL(drm_fb_helper_cfb_imageblit);
    874
    875/**
    876 * drm_fb_helper_set_suspend - wrapper around fb_set_suspend
    877 * @fb_helper: driver-allocated fbdev helper, can be NULL
    878 * @suspend: whether to suspend or resume
    879 *
    880 * A wrapper around fb_set_suspend implemented by fbdev core.
    881 * Use drm_fb_helper_set_suspend_unlocked() if you don't need to take
    882 * the lock yourself
    883 */
    884void drm_fb_helper_set_suspend(struct drm_fb_helper *fb_helper, bool suspend)
    885{
    886	if (fb_helper && fb_helper->fbdev)
    887		fb_set_suspend(fb_helper->fbdev, suspend);
    888}
    889EXPORT_SYMBOL(drm_fb_helper_set_suspend);
    890
    891/**
    892 * drm_fb_helper_set_suspend_unlocked - wrapper around fb_set_suspend that also
    893 *                                      takes the console lock
    894 * @fb_helper: driver-allocated fbdev helper, can be NULL
    895 * @suspend: whether to suspend or resume
    896 *
    897 * A wrapper around fb_set_suspend() that takes the console lock. If the lock
    898 * isn't available on resume, a worker is tasked with waiting for the lock
    899 * to become available. The console lock can be pretty contented on resume
    900 * due to all the printk activity.
    901 *
    902 * This function can be called multiple times with the same state since
    903 * &fb_info.state is checked to see if fbdev is running or not before locking.
    904 *
    905 * Use drm_fb_helper_set_suspend() if you need to take the lock yourself.
    906 */
    907void drm_fb_helper_set_suspend_unlocked(struct drm_fb_helper *fb_helper,
    908					bool suspend)
    909{
    910	if (!fb_helper || !fb_helper->fbdev)
    911		return;
    912
    913	/* make sure there's no pending/ongoing resume */
    914	flush_work(&fb_helper->resume_work);
    915
    916	if (suspend) {
    917		if (fb_helper->fbdev->state != FBINFO_STATE_RUNNING)
    918			return;
    919
    920		console_lock();
    921
    922	} else {
    923		if (fb_helper->fbdev->state == FBINFO_STATE_RUNNING)
    924			return;
    925
    926		if (!console_trylock()) {
    927			schedule_work(&fb_helper->resume_work);
    928			return;
    929		}
    930	}
    931
    932	fb_set_suspend(fb_helper->fbdev, suspend);
    933	console_unlock();
    934}
    935EXPORT_SYMBOL(drm_fb_helper_set_suspend_unlocked);
    936
    937static int setcmap_pseudo_palette(struct fb_cmap *cmap, struct fb_info *info)
    938{
    939	u32 *palette = (u32 *)info->pseudo_palette;
    940	int i;
    941
    942	if (cmap->start + cmap->len > 16)
    943		return -EINVAL;
    944
    945	for (i = 0; i < cmap->len; ++i) {
    946		u16 red = cmap->red[i];
    947		u16 green = cmap->green[i];
    948		u16 blue = cmap->blue[i];
    949		u32 value;
    950
    951		red >>= 16 - info->var.red.length;
    952		green >>= 16 - info->var.green.length;
    953		blue >>= 16 - info->var.blue.length;
    954		value = (red << info->var.red.offset) |
    955			(green << info->var.green.offset) |
    956			(blue << info->var.blue.offset);
    957		if (info->var.transp.length > 0) {
    958			u32 mask = (1 << info->var.transp.length) - 1;
    959
    960			mask <<= info->var.transp.offset;
    961			value |= mask;
    962		}
    963		palette[cmap->start + i] = value;
    964	}
    965
    966	return 0;
    967}
    968
    969static int setcmap_legacy(struct fb_cmap *cmap, struct fb_info *info)
    970{
    971	struct drm_fb_helper *fb_helper = info->par;
    972	struct drm_mode_set *modeset;
    973	struct drm_crtc *crtc;
    974	u16 *r, *g, *b;
    975	int ret = 0;
    976
    977	drm_modeset_lock_all(fb_helper->dev);
    978	drm_client_for_each_modeset(modeset, &fb_helper->client) {
    979		crtc = modeset->crtc;
    980		if (!crtc->funcs->gamma_set || !crtc->gamma_size) {
    981			ret = -EINVAL;
    982			goto out;
    983		}
    984
    985		if (cmap->start + cmap->len > crtc->gamma_size) {
    986			ret = -EINVAL;
    987			goto out;
    988		}
    989
    990		r = crtc->gamma_store;
    991		g = r + crtc->gamma_size;
    992		b = g + crtc->gamma_size;
    993
    994		memcpy(r + cmap->start, cmap->red, cmap->len * sizeof(*r));
    995		memcpy(g + cmap->start, cmap->green, cmap->len * sizeof(*g));
    996		memcpy(b + cmap->start, cmap->blue, cmap->len * sizeof(*b));
    997
    998		ret = crtc->funcs->gamma_set(crtc, r, g, b,
    999					     crtc->gamma_size, NULL);
   1000		if (ret)
   1001			goto out;
   1002	}
   1003out:
   1004	drm_modeset_unlock_all(fb_helper->dev);
   1005
   1006	return ret;
   1007}
   1008
   1009static struct drm_property_blob *setcmap_new_gamma_lut(struct drm_crtc *crtc,
   1010						       struct fb_cmap *cmap)
   1011{
   1012	struct drm_device *dev = crtc->dev;
   1013	struct drm_property_blob *gamma_lut;
   1014	struct drm_color_lut *lut;
   1015	int size = crtc->gamma_size;
   1016	int i;
   1017
   1018	if (!size || cmap->start + cmap->len > size)
   1019		return ERR_PTR(-EINVAL);
   1020
   1021	gamma_lut = drm_property_create_blob(dev, sizeof(*lut) * size, NULL);
   1022	if (IS_ERR(gamma_lut))
   1023		return gamma_lut;
   1024
   1025	lut = gamma_lut->data;
   1026	if (cmap->start || cmap->len != size) {
   1027		u16 *r = crtc->gamma_store;
   1028		u16 *g = r + crtc->gamma_size;
   1029		u16 *b = g + crtc->gamma_size;
   1030
   1031		for (i = 0; i < cmap->start; i++) {
   1032			lut[i].red = r[i];
   1033			lut[i].green = g[i];
   1034			lut[i].blue = b[i];
   1035		}
   1036		for (i = cmap->start + cmap->len; i < size; i++) {
   1037			lut[i].red = r[i];
   1038			lut[i].green = g[i];
   1039			lut[i].blue = b[i];
   1040		}
   1041	}
   1042
   1043	for (i = 0; i < cmap->len; i++) {
   1044		lut[cmap->start + i].red = cmap->red[i];
   1045		lut[cmap->start + i].green = cmap->green[i];
   1046		lut[cmap->start + i].blue = cmap->blue[i];
   1047	}
   1048
   1049	return gamma_lut;
   1050}
   1051
   1052static int setcmap_atomic(struct fb_cmap *cmap, struct fb_info *info)
   1053{
   1054	struct drm_fb_helper *fb_helper = info->par;
   1055	struct drm_device *dev = fb_helper->dev;
   1056	struct drm_property_blob *gamma_lut = NULL;
   1057	struct drm_modeset_acquire_ctx ctx;
   1058	struct drm_crtc_state *crtc_state;
   1059	struct drm_atomic_state *state;
   1060	struct drm_mode_set *modeset;
   1061	struct drm_crtc *crtc;
   1062	u16 *r, *g, *b;
   1063	bool replaced;
   1064	int ret = 0;
   1065
   1066	drm_modeset_acquire_init(&ctx, 0);
   1067
   1068	state = drm_atomic_state_alloc(dev);
   1069	if (!state) {
   1070		ret = -ENOMEM;
   1071		goto out_ctx;
   1072	}
   1073
   1074	state->acquire_ctx = &ctx;
   1075retry:
   1076	drm_client_for_each_modeset(modeset, &fb_helper->client) {
   1077		crtc = modeset->crtc;
   1078
   1079		if (!gamma_lut)
   1080			gamma_lut = setcmap_new_gamma_lut(crtc, cmap);
   1081		if (IS_ERR(gamma_lut)) {
   1082			ret = PTR_ERR(gamma_lut);
   1083			gamma_lut = NULL;
   1084			goto out_state;
   1085		}
   1086
   1087		crtc_state = drm_atomic_get_crtc_state(state, crtc);
   1088		if (IS_ERR(crtc_state)) {
   1089			ret = PTR_ERR(crtc_state);
   1090			goto out_state;
   1091		}
   1092
   1093		/*
   1094		 * FIXME: This always uses gamma_lut. Some HW have only
   1095		 * degamma_lut, in which case we should reset gamma_lut and set
   1096		 * degamma_lut. See drm_crtc_legacy_gamma_set().
   1097		 */
   1098		replaced  = drm_property_replace_blob(&crtc_state->degamma_lut,
   1099						      NULL);
   1100		replaced |= drm_property_replace_blob(&crtc_state->ctm, NULL);
   1101		replaced |= drm_property_replace_blob(&crtc_state->gamma_lut,
   1102						      gamma_lut);
   1103		crtc_state->color_mgmt_changed |= replaced;
   1104	}
   1105
   1106	ret = drm_atomic_commit(state);
   1107	if (ret)
   1108		goto out_state;
   1109
   1110	drm_client_for_each_modeset(modeset, &fb_helper->client) {
   1111		crtc = modeset->crtc;
   1112
   1113		r = crtc->gamma_store;
   1114		g = r + crtc->gamma_size;
   1115		b = g + crtc->gamma_size;
   1116
   1117		memcpy(r + cmap->start, cmap->red, cmap->len * sizeof(*r));
   1118		memcpy(g + cmap->start, cmap->green, cmap->len * sizeof(*g));
   1119		memcpy(b + cmap->start, cmap->blue, cmap->len * sizeof(*b));
   1120	}
   1121
   1122out_state:
   1123	if (ret == -EDEADLK)
   1124		goto backoff;
   1125
   1126	drm_property_blob_put(gamma_lut);
   1127	drm_atomic_state_put(state);
   1128out_ctx:
   1129	drm_modeset_drop_locks(&ctx);
   1130	drm_modeset_acquire_fini(&ctx);
   1131
   1132	return ret;
   1133
   1134backoff:
   1135	drm_atomic_state_clear(state);
   1136	drm_modeset_backoff(&ctx);
   1137	goto retry;
   1138}
   1139
   1140/**
   1141 * drm_fb_helper_setcmap - implementation for &fb_ops.fb_setcmap
   1142 * @cmap: cmap to set
   1143 * @info: fbdev registered by the helper
   1144 */
   1145int drm_fb_helper_setcmap(struct fb_cmap *cmap, struct fb_info *info)
   1146{
   1147	struct drm_fb_helper *fb_helper = info->par;
   1148	struct drm_device *dev = fb_helper->dev;
   1149	int ret;
   1150
   1151	if (oops_in_progress)
   1152		return -EBUSY;
   1153
   1154	mutex_lock(&fb_helper->lock);
   1155
   1156	if (!drm_master_internal_acquire(dev)) {
   1157		ret = -EBUSY;
   1158		goto unlock;
   1159	}
   1160
   1161	mutex_lock(&fb_helper->client.modeset_mutex);
   1162	if (info->fix.visual == FB_VISUAL_TRUECOLOR)
   1163		ret = setcmap_pseudo_palette(cmap, info);
   1164	else if (drm_drv_uses_atomic_modeset(fb_helper->dev))
   1165		ret = setcmap_atomic(cmap, info);
   1166	else
   1167		ret = setcmap_legacy(cmap, info);
   1168	mutex_unlock(&fb_helper->client.modeset_mutex);
   1169
   1170	drm_master_internal_release(dev);
   1171unlock:
   1172	mutex_unlock(&fb_helper->lock);
   1173
   1174	return ret;
   1175}
   1176EXPORT_SYMBOL(drm_fb_helper_setcmap);
   1177
   1178/**
   1179 * drm_fb_helper_ioctl - legacy ioctl implementation
   1180 * @info: fbdev registered by the helper
   1181 * @cmd: ioctl command
   1182 * @arg: ioctl argument
   1183 *
   1184 * A helper to implement the standard fbdev ioctl. Only
   1185 * FBIO_WAITFORVSYNC is implemented for now.
   1186 */
   1187int drm_fb_helper_ioctl(struct fb_info *info, unsigned int cmd,
   1188			unsigned long arg)
   1189{
   1190	struct drm_fb_helper *fb_helper = info->par;
   1191	struct drm_device *dev = fb_helper->dev;
   1192	struct drm_crtc *crtc;
   1193	int ret = 0;
   1194
   1195	mutex_lock(&fb_helper->lock);
   1196	if (!drm_master_internal_acquire(dev)) {
   1197		ret = -EBUSY;
   1198		goto unlock;
   1199	}
   1200
   1201	switch (cmd) {
   1202	case FBIO_WAITFORVSYNC:
   1203		/*
   1204		 * Only consider the first CRTC.
   1205		 *
   1206		 * This ioctl is supposed to take the CRTC number as
   1207		 * an argument, but in fbdev times, what that number
   1208		 * was supposed to be was quite unclear, different
   1209		 * drivers were passing that argument differently
   1210		 * (some by reference, some by value), and most of the
   1211		 * userspace applications were just hardcoding 0 as an
   1212		 * argument.
   1213		 *
   1214		 * The first CRTC should be the integrated panel on
   1215		 * most drivers, so this is the best choice we can
   1216		 * make. If we're not smart enough here, one should
   1217		 * just consider switch the userspace to KMS.
   1218		 */
   1219		crtc = fb_helper->client.modesets[0].crtc;
   1220
   1221		/*
   1222		 * Only wait for a vblank event if the CRTC is
   1223		 * enabled, otherwise just don't do anythintg,
   1224		 * not even report an error.
   1225		 */
   1226		ret = drm_crtc_vblank_get(crtc);
   1227		if (!ret) {
   1228			drm_crtc_wait_one_vblank(crtc);
   1229			drm_crtc_vblank_put(crtc);
   1230		}
   1231
   1232		ret = 0;
   1233		break;
   1234	default:
   1235		ret = -ENOTTY;
   1236	}
   1237
   1238	drm_master_internal_release(dev);
   1239unlock:
   1240	mutex_unlock(&fb_helper->lock);
   1241	return ret;
   1242}
   1243EXPORT_SYMBOL(drm_fb_helper_ioctl);
   1244
   1245static bool drm_fb_pixel_format_equal(const struct fb_var_screeninfo *var_1,
   1246				      const struct fb_var_screeninfo *var_2)
   1247{
   1248	return var_1->bits_per_pixel == var_2->bits_per_pixel &&
   1249	       var_1->grayscale == var_2->grayscale &&
   1250	       var_1->red.offset == var_2->red.offset &&
   1251	       var_1->red.length == var_2->red.length &&
   1252	       var_1->red.msb_right == var_2->red.msb_right &&
   1253	       var_1->green.offset == var_2->green.offset &&
   1254	       var_1->green.length == var_2->green.length &&
   1255	       var_1->green.msb_right == var_2->green.msb_right &&
   1256	       var_1->blue.offset == var_2->blue.offset &&
   1257	       var_1->blue.length == var_2->blue.length &&
   1258	       var_1->blue.msb_right == var_2->blue.msb_right &&
   1259	       var_1->transp.offset == var_2->transp.offset &&
   1260	       var_1->transp.length == var_2->transp.length &&
   1261	       var_1->transp.msb_right == var_2->transp.msb_right;
   1262}
   1263
   1264static void drm_fb_helper_fill_pixel_fmt(struct fb_var_screeninfo *var,
   1265					 u8 depth)
   1266{
   1267	switch (depth) {
   1268	case 8:
   1269		var->red.offset = 0;
   1270		var->green.offset = 0;
   1271		var->blue.offset = 0;
   1272		var->red.length = 8; /* 8bit DAC */
   1273		var->green.length = 8;
   1274		var->blue.length = 8;
   1275		var->transp.offset = 0;
   1276		var->transp.length = 0;
   1277		break;
   1278	case 15:
   1279		var->red.offset = 10;
   1280		var->green.offset = 5;
   1281		var->blue.offset = 0;
   1282		var->red.length = 5;
   1283		var->green.length = 5;
   1284		var->blue.length = 5;
   1285		var->transp.offset = 15;
   1286		var->transp.length = 1;
   1287		break;
   1288	case 16:
   1289		var->red.offset = 11;
   1290		var->green.offset = 5;
   1291		var->blue.offset = 0;
   1292		var->red.length = 5;
   1293		var->green.length = 6;
   1294		var->blue.length = 5;
   1295		var->transp.offset = 0;
   1296		break;
   1297	case 24:
   1298		var->red.offset = 16;
   1299		var->green.offset = 8;
   1300		var->blue.offset = 0;
   1301		var->red.length = 8;
   1302		var->green.length = 8;
   1303		var->blue.length = 8;
   1304		var->transp.offset = 0;
   1305		var->transp.length = 0;
   1306		break;
   1307	case 32:
   1308		var->red.offset = 16;
   1309		var->green.offset = 8;
   1310		var->blue.offset = 0;
   1311		var->red.length = 8;
   1312		var->green.length = 8;
   1313		var->blue.length = 8;
   1314		var->transp.offset = 24;
   1315		var->transp.length = 8;
   1316		break;
   1317	default:
   1318		break;
   1319	}
   1320}
   1321
   1322/**
   1323 * drm_fb_helper_check_var - implementation for &fb_ops.fb_check_var
   1324 * @var: screeninfo to check
   1325 * @info: fbdev registered by the helper
   1326 */
   1327int drm_fb_helper_check_var(struct fb_var_screeninfo *var,
   1328			    struct fb_info *info)
   1329{
   1330	struct drm_fb_helper *fb_helper = info->par;
   1331	struct drm_framebuffer *fb = fb_helper->fb;
   1332	struct drm_device *dev = fb_helper->dev;
   1333
   1334	if (in_dbg_master())
   1335		return -EINVAL;
   1336
   1337	if (var->pixclock != 0) {
   1338		drm_dbg_kms(dev, "fbdev emulation doesn't support changing the pixel clock, value of pixclock is ignored\n");
   1339		var->pixclock = 0;
   1340	}
   1341
   1342	if ((drm_format_info_block_width(fb->format, 0) > 1) ||
   1343	    (drm_format_info_block_height(fb->format, 0) > 1))
   1344		return -EINVAL;
   1345
   1346	/*
   1347	 * Changes struct fb_var_screeninfo are currently not pushed back
   1348	 * to KMS, hence fail if different settings are requested.
   1349	 */
   1350	if (var->bits_per_pixel > fb->format->cpp[0] * 8 ||
   1351	    var->xres > fb->width || var->yres > fb->height ||
   1352	    var->xres_virtual > fb->width || var->yres_virtual > fb->height) {
   1353		drm_dbg_kms(dev, "fb requested width/height/bpp can't fit in current fb "
   1354			  "request %dx%d-%d (virtual %dx%d) > %dx%d-%d\n",
   1355			  var->xres, var->yres, var->bits_per_pixel,
   1356			  var->xres_virtual, var->yres_virtual,
   1357			  fb->width, fb->height, fb->format->cpp[0] * 8);
   1358		return -EINVAL;
   1359	}
   1360
   1361	/*
   1362	 * Workaround for SDL 1.2, which is known to be setting all pixel format
   1363	 * fields values to zero in some cases. We treat this situation as a
   1364	 * kind of "use some reasonable autodetected values".
   1365	 */
   1366	if (!var->red.offset     && !var->green.offset    &&
   1367	    !var->blue.offset    && !var->transp.offset   &&
   1368	    !var->red.length     && !var->green.length    &&
   1369	    !var->blue.length    && !var->transp.length   &&
   1370	    !var->red.msb_right  && !var->green.msb_right &&
   1371	    !var->blue.msb_right && !var->transp.msb_right) {
   1372		drm_fb_helper_fill_pixel_fmt(var, fb->format->depth);
   1373	}
   1374
   1375	/*
   1376	 * Likewise, bits_per_pixel should be rounded up to a supported value.
   1377	 */
   1378	var->bits_per_pixel = fb->format->cpp[0] * 8;
   1379
   1380	/*
   1381	 * drm fbdev emulation doesn't support changing the pixel format at all,
   1382	 * so reject all pixel format changing requests.
   1383	 */
   1384	if (!drm_fb_pixel_format_equal(var, &info->var)) {
   1385		drm_dbg_kms(dev, "fbdev emulation doesn't support changing the pixel format\n");
   1386		return -EINVAL;
   1387	}
   1388
   1389	return 0;
   1390}
   1391EXPORT_SYMBOL(drm_fb_helper_check_var);
   1392
   1393/**
   1394 * drm_fb_helper_set_par - implementation for &fb_ops.fb_set_par
   1395 * @info: fbdev registered by the helper
   1396 *
   1397 * This will let fbcon do the mode init and is called at initialization time by
   1398 * the fbdev core when registering the driver, and later on through the hotplug
   1399 * callback.
   1400 */
   1401int drm_fb_helper_set_par(struct fb_info *info)
   1402{
   1403	struct drm_fb_helper *fb_helper = info->par;
   1404	struct fb_var_screeninfo *var = &info->var;
   1405	bool force;
   1406
   1407	if (oops_in_progress)
   1408		return -EBUSY;
   1409
   1410	if (var->pixclock != 0) {
   1411		drm_err(fb_helper->dev, "PIXEL CLOCK SET\n");
   1412		return -EINVAL;
   1413	}
   1414
   1415	/*
   1416	 * Normally we want to make sure that a kms master takes precedence over
   1417	 * fbdev, to avoid fbdev flickering and occasionally stealing the
   1418	 * display status. But Xorg first sets the vt back to text mode using
   1419	 * the KDSET IOCTL with KD_TEXT, and only after that drops the master
   1420	 * status when exiting.
   1421	 *
   1422	 * In the past this was caught by drm_fb_helper_lastclose(), but on
   1423	 * modern systems where logind always keeps a drm fd open to orchestrate
   1424	 * the vt switching, this doesn't work.
   1425	 *
   1426	 * To not break the userspace ABI we have this special case here, which
   1427	 * is only used for the above case. Everything else uses the normal
   1428	 * commit function, which ensures that we never steal the display from
   1429	 * an active drm master.
   1430	 */
   1431	force = var->activate & FB_ACTIVATE_KD_TEXT;
   1432
   1433	__drm_fb_helper_restore_fbdev_mode_unlocked(fb_helper, force);
   1434
   1435	return 0;
   1436}
   1437EXPORT_SYMBOL(drm_fb_helper_set_par);
   1438
   1439static void pan_set(struct drm_fb_helper *fb_helper, int x, int y)
   1440{
   1441	struct drm_mode_set *mode_set;
   1442
   1443	mutex_lock(&fb_helper->client.modeset_mutex);
   1444	drm_client_for_each_modeset(mode_set, &fb_helper->client) {
   1445		mode_set->x = x;
   1446		mode_set->y = y;
   1447	}
   1448	mutex_unlock(&fb_helper->client.modeset_mutex);
   1449}
   1450
   1451static int pan_display_atomic(struct fb_var_screeninfo *var,
   1452			      struct fb_info *info)
   1453{
   1454	struct drm_fb_helper *fb_helper = info->par;
   1455	int ret;
   1456
   1457	pan_set(fb_helper, var->xoffset, var->yoffset);
   1458
   1459	ret = drm_client_modeset_commit_locked(&fb_helper->client);
   1460	if (!ret) {
   1461		info->var.xoffset = var->xoffset;
   1462		info->var.yoffset = var->yoffset;
   1463	} else
   1464		pan_set(fb_helper, info->var.xoffset, info->var.yoffset);
   1465
   1466	return ret;
   1467}
   1468
   1469static int pan_display_legacy(struct fb_var_screeninfo *var,
   1470			      struct fb_info *info)
   1471{
   1472	struct drm_fb_helper *fb_helper = info->par;
   1473	struct drm_client_dev *client = &fb_helper->client;
   1474	struct drm_mode_set *modeset;
   1475	int ret = 0;
   1476
   1477	mutex_lock(&client->modeset_mutex);
   1478	drm_modeset_lock_all(fb_helper->dev);
   1479	drm_client_for_each_modeset(modeset, client) {
   1480		modeset->x = var->xoffset;
   1481		modeset->y = var->yoffset;
   1482
   1483		if (modeset->num_connectors) {
   1484			ret = drm_mode_set_config_internal(modeset);
   1485			if (!ret) {
   1486				info->var.xoffset = var->xoffset;
   1487				info->var.yoffset = var->yoffset;
   1488			}
   1489		}
   1490	}
   1491	drm_modeset_unlock_all(fb_helper->dev);
   1492	mutex_unlock(&client->modeset_mutex);
   1493
   1494	return ret;
   1495}
   1496
   1497/**
   1498 * drm_fb_helper_pan_display - implementation for &fb_ops.fb_pan_display
   1499 * @var: updated screen information
   1500 * @info: fbdev registered by the helper
   1501 */
   1502int drm_fb_helper_pan_display(struct fb_var_screeninfo *var,
   1503			      struct fb_info *info)
   1504{
   1505	struct drm_fb_helper *fb_helper = info->par;
   1506	struct drm_device *dev = fb_helper->dev;
   1507	int ret;
   1508
   1509	if (oops_in_progress)
   1510		return -EBUSY;
   1511
   1512	mutex_lock(&fb_helper->lock);
   1513	if (!drm_master_internal_acquire(dev)) {
   1514		ret = -EBUSY;
   1515		goto unlock;
   1516	}
   1517
   1518	if (drm_drv_uses_atomic_modeset(dev))
   1519		ret = pan_display_atomic(var, info);
   1520	else
   1521		ret = pan_display_legacy(var, info);
   1522
   1523	drm_master_internal_release(dev);
   1524unlock:
   1525	mutex_unlock(&fb_helper->lock);
   1526
   1527	return ret;
   1528}
   1529EXPORT_SYMBOL(drm_fb_helper_pan_display);
   1530
   1531/*
   1532 * Allocates the backing storage and sets up the fbdev info structure through
   1533 * the ->fb_probe callback.
   1534 */
   1535static int drm_fb_helper_single_fb_probe(struct drm_fb_helper *fb_helper,
   1536					 int preferred_bpp)
   1537{
   1538	struct drm_client_dev *client = &fb_helper->client;
   1539	struct drm_device *dev = fb_helper->dev;
   1540	struct drm_mode_config *config = &dev->mode_config;
   1541	int ret = 0;
   1542	int crtc_count = 0;
   1543	struct drm_connector_list_iter conn_iter;
   1544	struct drm_fb_helper_surface_size sizes;
   1545	struct drm_connector *connector;
   1546	struct drm_mode_set *mode_set;
   1547	int best_depth = 0;
   1548
   1549	memset(&sizes, 0, sizeof(struct drm_fb_helper_surface_size));
   1550	sizes.surface_depth = 24;
   1551	sizes.surface_bpp = 32;
   1552	sizes.fb_width = (u32)-1;
   1553	sizes.fb_height = (u32)-1;
   1554
   1555	/*
   1556	 * If driver picks 8 or 16 by default use that for both depth/bpp
   1557	 * to begin with
   1558	 */
   1559	if (preferred_bpp != sizes.surface_bpp)
   1560		sizes.surface_depth = sizes.surface_bpp = preferred_bpp;
   1561
   1562	drm_connector_list_iter_begin(fb_helper->dev, &conn_iter);
   1563	drm_client_for_each_connector_iter(connector, &conn_iter) {
   1564		struct drm_cmdline_mode *cmdline_mode;
   1565
   1566		cmdline_mode = &connector->cmdline_mode;
   1567
   1568		if (cmdline_mode->bpp_specified) {
   1569			switch (cmdline_mode->bpp) {
   1570			case 8:
   1571				sizes.surface_depth = sizes.surface_bpp = 8;
   1572				break;
   1573			case 15:
   1574				sizes.surface_depth = 15;
   1575				sizes.surface_bpp = 16;
   1576				break;
   1577			case 16:
   1578				sizes.surface_depth = sizes.surface_bpp = 16;
   1579				break;
   1580			case 24:
   1581				sizes.surface_depth = sizes.surface_bpp = 24;
   1582				break;
   1583			case 32:
   1584				sizes.surface_depth = 24;
   1585				sizes.surface_bpp = 32;
   1586				break;
   1587			}
   1588			break;
   1589		}
   1590	}
   1591	drm_connector_list_iter_end(&conn_iter);
   1592
   1593	/*
   1594	 * If we run into a situation where, for example, the primary plane
   1595	 * supports RGBA5551 (16 bpp, depth 15) but not RGB565 (16 bpp, depth
   1596	 * 16) we need to scale down the depth of the sizes we request.
   1597	 */
   1598	mutex_lock(&client->modeset_mutex);
   1599	drm_client_for_each_modeset(mode_set, client) {
   1600		struct drm_crtc *crtc = mode_set->crtc;
   1601		struct drm_plane *plane = crtc->primary;
   1602		int j;
   1603
   1604		drm_dbg_kms(dev, "test CRTC %u primary plane\n", drm_crtc_index(crtc));
   1605
   1606		for (j = 0; j < plane->format_count; j++) {
   1607			const struct drm_format_info *fmt;
   1608
   1609			fmt = drm_format_info(plane->format_types[j]);
   1610
   1611			/*
   1612			 * Do not consider YUV or other complicated formats
   1613			 * for framebuffers. This means only legacy formats
   1614			 * are supported (fmt->depth is a legacy field) but
   1615			 * the framebuffer emulation can only deal with such
   1616			 * formats, specifically RGB/BGA formats.
   1617			 */
   1618			if (fmt->depth == 0)
   1619				continue;
   1620
   1621			/* We found a perfect fit, great */
   1622			if (fmt->depth == sizes.surface_depth) {
   1623				best_depth = fmt->depth;
   1624				break;
   1625			}
   1626
   1627			/* Skip depths above what we're looking for */
   1628			if (fmt->depth > sizes.surface_depth)
   1629				continue;
   1630
   1631			/* Best depth found so far */
   1632			if (fmt->depth > best_depth)
   1633				best_depth = fmt->depth;
   1634		}
   1635	}
   1636	if (sizes.surface_depth != best_depth && best_depth) {
   1637		drm_info(dev, "requested bpp %d, scaled depth down to %d",
   1638			 sizes.surface_bpp, best_depth);
   1639		sizes.surface_depth = best_depth;
   1640	}
   1641
   1642	/* first up get a count of crtcs now in use and new min/maxes width/heights */
   1643	crtc_count = 0;
   1644	drm_client_for_each_modeset(mode_set, client) {
   1645		struct drm_display_mode *desired_mode;
   1646		int x, y, j;
   1647		/* in case of tile group, are we the last tile vert or horiz?
   1648		 * If no tile group you are always the last one both vertically
   1649		 * and horizontally
   1650		 */
   1651		bool lastv = true, lasth = true;
   1652
   1653		desired_mode = mode_set->mode;
   1654
   1655		if (!desired_mode)
   1656			continue;
   1657
   1658		crtc_count++;
   1659
   1660		x = mode_set->x;
   1661		y = mode_set->y;
   1662
   1663		sizes.surface_width  = max_t(u32, desired_mode->hdisplay + x, sizes.surface_width);
   1664		sizes.surface_height = max_t(u32, desired_mode->vdisplay + y, sizes.surface_height);
   1665
   1666		for (j = 0; j < mode_set->num_connectors; j++) {
   1667			struct drm_connector *connector = mode_set->connectors[j];
   1668
   1669			if (connector->has_tile &&
   1670			    desired_mode->hdisplay == connector->tile_h_size &&
   1671			    desired_mode->vdisplay == connector->tile_v_size) {
   1672				lasth = (connector->tile_h_loc == (connector->num_h_tile - 1));
   1673				lastv = (connector->tile_v_loc == (connector->num_v_tile - 1));
   1674				/* cloning to multiple tiles is just crazy-talk, so: */
   1675				break;
   1676			}
   1677		}
   1678
   1679		if (lasth)
   1680			sizes.fb_width  = min_t(u32, desired_mode->hdisplay + x, sizes.fb_width);
   1681		if (lastv)
   1682			sizes.fb_height = min_t(u32, desired_mode->vdisplay + y, sizes.fb_height);
   1683	}
   1684	mutex_unlock(&client->modeset_mutex);
   1685
   1686	if (crtc_count == 0 || sizes.fb_width == -1 || sizes.fb_height == -1) {
   1687		drm_info(dev, "Cannot find any crtc or sizes\n");
   1688
   1689		/* First time: disable all crtc's.. */
   1690		if (!fb_helper->deferred_setup)
   1691			drm_client_modeset_commit(client);
   1692		return -EAGAIN;
   1693	}
   1694
   1695	/* Handle our overallocation */
   1696	sizes.surface_height *= drm_fbdev_overalloc;
   1697	sizes.surface_height /= 100;
   1698	if (sizes.surface_height > config->max_height) {
   1699		drm_dbg_kms(dev, "Fbdev over-allocation too large; clamping height to %d\n",
   1700			    config->max_height);
   1701		sizes.surface_height = config->max_height;
   1702	}
   1703
   1704	/* push down into drivers */
   1705	ret = (*fb_helper->funcs->fb_probe)(fb_helper, &sizes);
   1706	if (ret < 0)
   1707		return ret;
   1708
   1709	strcpy(fb_helper->fb->comm, "[fbcon]");
   1710	return 0;
   1711}
   1712
   1713static void drm_fb_helper_fill_fix(struct fb_info *info, uint32_t pitch,
   1714				   uint32_t depth)
   1715{
   1716	info->fix.type = FB_TYPE_PACKED_PIXELS;
   1717	info->fix.visual = depth == 8 ? FB_VISUAL_PSEUDOCOLOR :
   1718		FB_VISUAL_TRUECOLOR;
   1719	info->fix.mmio_start = 0;
   1720	info->fix.mmio_len = 0;
   1721	info->fix.type_aux = 0;
   1722	info->fix.xpanstep = 1; /* doing it in hw */
   1723	info->fix.ypanstep = 1; /* doing it in hw */
   1724	info->fix.ywrapstep = 0;
   1725	info->fix.accel = FB_ACCEL_NONE;
   1726
   1727	info->fix.line_length = pitch;
   1728}
   1729
   1730static void drm_fb_helper_fill_var(struct fb_info *info,
   1731				   struct drm_fb_helper *fb_helper,
   1732				   uint32_t fb_width, uint32_t fb_height)
   1733{
   1734	struct drm_framebuffer *fb = fb_helper->fb;
   1735
   1736	WARN_ON((drm_format_info_block_width(fb->format, 0) > 1) ||
   1737		(drm_format_info_block_height(fb->format, 0) > 1));
   1738	info->pseudo_palette = fb_helper->pseudo_palette;
   1739	info->var.xres_virtual = fb->width;
   1740	info->var.yres_virtual = fb->height;
   1741	info->var.bits_per_pixel = fb->format->cpp[0] * 8;
   1742	info->var.accel_flags = FB_ACCELF_TEXT;
   1743	info->var.xoffset = 0;
   1744	info->var.yoffset = 0;
   1745	info->var.activate = FB_ACTIVATE_NOW;
   1746
   1747	drm_fb_helper_fill_pixel_fmt(&info->var, fb->format->depth);
   1748
   1749	info->var.xres = fb_width;
   1750	info->var.yres = fb_height;
   1751}
   1752
   1753/**
   1754 * drm_fb_helper_fill_info - initializes fbdev information
   1755 * @info: fbdev instance to set up
   1756 * @fb_helper: fb helper instance to use as template
   1757 * @sizes: describes fbdev size and scanout surface size
   1758 *
   1759 * Sets up the variable and fixed fbdev metainformation from the given fb helper
   1760 * instance and the drm framebuffer allocated in &drm_fb_helper.fb.
   1761 *
   1762 * Drivers should call this (or their equivalent setup code) from their
   1763 * &drm_fb_helper_funcs.fb_probe callback after having allocated the fbdev
   1764 * backing storage framebuffer.
   1765 */
   1766void drm_fb_helper_fill_info(struct fb_info *info,
   1767			     struct drm_fb_helper *fb_helper,
   1768			     struct drm_fb_helper_surface_size *sizes)
   1769{
   1770	struct drm_framebuffer *fb = fb_helper->fb;
   1771
   1772	drm_fb_helper_fill_fix(info, fb->pitches[0], fb->format->depth);
   1773	drm_fb_helper_fill_var(info, fb_helper,
   1774			       sizes->fb_width, sizes->fb_height);
   1775
   1776	info->par = fb_helper;
   1777	/*
   1778	 * The DRM drivers fbdev emulation device name can be confusing if the
   1779	 * driver name also has a "drm" suffix on it. Leading to names such as
   1780	 * "simpledrmdrmfb" in /proc/fb. Unfortunately, it's an uAPI and can't
   1781	 * be changed due user-space tools (e.g: pm-utils) matching against it.
   1782	 */
   1783	snprintf(info->fix.id, sizeof(info->fix.id), "%sdrmfb",
   1784		 fb_helper->dev->driver->name);
   1785
   1786}
   1787EXPORT_SYMBOL(drm_fb_helper_fill_info);
   1788
   1789/*
   1790 * This is a continuation of drm_setup_crtcs() that sets up anything related
   1791 * to the framebuffer. During initialization, drm_setup_crtcs() is called before
   1792 * the framebuffer has been allocated (fb_helper->fb and fb_helper->fbdev).
   1793 * So, any setup that touches those fields needs to be done here instead of in
   1794 * drm_setup_crtcs().
   1795 */
   1796static void drm_setup_crtcs_fb(struct drm_fb_helper *fb_helper)
   1797{
   1798	struct drm_client_dev *client = &fb_helper->client;
   1799	struct drm_connector_list_iter conn_iter;
   1800	struct fb_info *info = fb_helper->fbdev;
   1801	unsigned int rotation, sw_rotations = 0;
   1802	struct drm_connector *connector;
   1803	struct drm_mode_set *modeset;
   1804
   1805	mutex_lock(&client->modeset_mutex);
   1806	drm_client_for_each_modeset(modeset, client) {
   1807		if (!modeset->num_connectors)
   1808			continue;
   1809
   1810		modeset->fb = fb_helper->fb;
   1811
   1812		if (drm_client_rotation(modeset, &rotation))
   1813			/* Rotating in hardware, fbcon should not rotate */
   1814			sw_rotations |= DRM_MODE_ROTATE_0;
   1815		else
   1816			sw_rotations |= rotation;
   1817	}
   1818	mutex_unlock(&client->modeset_mutex);
   1819
   1820	drm_connector_list_iter_begin(fb_helper->dev, &conn_iter);
   1821	drm_client_for_each_connector_iter(connector, &conn_iter) {
   1822
   1823		/* use first connected connector for the physical dimensions */
   1824		if (connector->status == connector_status_connected) {
   1825			info->var.width = connector->display_info.width_mm;
   1826			info->var.height = connector->display_info.height_mm;
   1827			break;
   1828		}
   1829	}
   1830	drm_connector_list_iter_end(&conn_iter);
   1831
   1832	switch (sw_rotations) {
   1833	case DRM_MODE_ROTATE_0:
   1834		info->fbcon_rotate_hint = FB_ROTATE_UR;
   1835		break;
   1836	case DRM_MODE_ROTATE_90:
   1837		info->fbcon_rotate_hint = FB_ROTATE_CCW;
   1838		break;
   1839	case DRM_MODE_ROTATE_180:
   1840		info->fbcon_rotate_hint = FB_ROTATE_UD;
   1841		break;
   1842	case DRM_MODE_ROTATE_270:
   1843		info->fbcon_rotate_hint = FB_ROTATE_CW;
   1844		break;
   1845	default:
   1846		/*
   1847		 * Multiple bits are set / multiple rotations requested
   1848		 * fbcon cannot handle separate rotation settings per
   1849		 * output, so fallback to unrotated.
   1850		 */
   1851		info->fbcon_rotate_hint = FB_ROTATE_UR;
   1852	}
   1853}
   1854
   1855/* Note: Drops fb_helper->lock before returning. */
   1856static int
   1857__drm_fb_helper_initial_config_and_unlock(struct drm_fb_helper *fb_helper,
   1858					  int bpp_sel)
   1859{
   1860	struct drm_device *dev = fb_helper->dev;
   1861	struct fb_info *info;
   1862	unsigned int width, height;
   1863	int ret;
   1864
   1865	width = dev->mode_config.max_width;
   1866	height = dev->mode_config.max_height;
   1867
   1868	drm_client_modeset_probe(&fb_helper->client, width, height);
   1869	ret = drm_fb_helper_single_fb_probe(fb_helper, bpp_sel);
   1870	if (ret < 0) {
   1871		if (ret == -EAGAIN) {
   1872			fb_helper->preferred_bpp = bpp_sel;
   1873			fb_helper->deferred_setup = true;
   1874			ret = 0;
   1875		}
   1876		mutex_unlock(&fb_helper->lock);
   1877
   1878		return ret;
   1879	}
   1880	drm_setup_crtcs_fb(fb_helper);
   1881
   1882	fb_helper->deferred_setup = false;
   1883
   1884	info = fb_helper->fbdev;
   1885	info->var.pixclock = 0;
   1886	/* Shamelessly allow physical address leaking to userspace */
   1887#if IS_ENABLED(CONFIG_DRM_FBDEV_LEAK_PHYS_SMEM)
   1888	if (!drm_leak_fbdev_smem)
   1889#endif
   1890		/* don't leak any physical addresses to userspace */
   1891		info->flags |= FBINFO_HIDE_SMEM_START;
   1892
   1893	/* Need to drop locks to avoid recursive deadlock in
   1894	 * register_framebuffer. This is ok because the only thing left to do is
   1895	 * register the fbdev emulation instance in kernel_fb_helper_list. */
   1896	mutex_unlock(&fb_helper->lock);
   1897
   1898	ret = register_framebuffer(info);
   1899	if (ret < 0)
   1900		return ret;
   1901
   1902	drm_info(dev, "fb%d: %s frame buffer device\n",
   1903		 info->node, info->fix.id);
   1904
   1905	mutex_lock(&kernel_fb_helper_lock);
   1906	if (list_empty(&kernel_fb_helper_list))
   1907		register_sysrq_key('v', &sysrq_drm_fb_helper_restore_op);
   1908
   1909	list_add(&fb_helper->kernel_fb_list, &kernel_fb_helper_list);
   1910	mutex_unlock(&kernel_fb_helper_lock);
   1911
   1912	return 0;
   1913}
   1914
   1915/**
   1916 * drm_fb_helper_initial_config - setup a sane initial connector configuration
   1917 * @fb_helper: fb_helper device struct
   1918 * @bpp_sel: bpp value to use for the framebuffer configuration
   1919 *
   1920 * Scans the CRTCs and connectors and tries to put together an initial setup.
   1921 * At the moment, this is a cloned configuration across all heads with
   1922 * a new framebuffer object as the backing store.
   1923 *
   1924 * Note that this also registers the fbdev and so allows userspace to call into
   1925 * the driver through the fbdev interfaces.
   1926 *
   1927 * This function will call down into the &drm_fb_helper_funcs.fb_probe callback
   1928 * to let the driver allocate and initialize the fbdev info structure and the
   1929 * drm framebuffer used to back the fbdev. drm_fb_helper_fill_info() is provided
   1930 * as a helper to setup simple default values for the fbdev info structure.
   1931 *
   1932 * HANG DEBUGGING:
   1933 *
   1934 * When you have fbcon support built-in or already loaded, this function will do
   1935 * a full modeset to setup the fbdev console. Due to locking misdesign in the
   1936 * VT/fbdev subsystem that entire modeset sequence has to be done while holding
   1937 * console_lock. Until console_unlock is called no dmesg lines will be sent out
   1938 * to consoles, not even serial console. This means when your driver crashes,
   1939 * you will see absolutely nothing else but a system stuck in this function,
   1940 * with no further output. Any kind of printk() you place within your own driver
   1941 * or in the drm core modeset code will also never show up.
   1942 *
   1943 * Standard debug practice is to run the fbcon setup without taking the
   1944 * console_lock as a hack, to be able to see backtraces and crashes on the
   1945 * serial line. This can be done by setting the fb.lockless_register_fb=1 kernel
   1946 * cmdline option.
   1947 *
   1948 * The other option is to just disable fbdev emulation since very likely the
   1949 * first modeset from userspace will crash in the same way, and is even easier
   1950 * to debug. This can be done by setting the drm_kms_helper.fbdev_emulation=0
   1951 * kernel cmdline option.
   1952 *
   1953 * RETURNS:
   1954 * Zero if everything went ok, nonzero otherwise.
   1955 */
   1956int drm_fb_helper_initial_config(struct drm_fb_helper *fb_helper, int bpp_sel)
   1957{
   1958	int ret;
   1959
   1960	if (!drm_fbdev_emulation)
   1961		return 0;
   1962
   1963	mutex_lock(&fb_helper->lock);
   1964	ret = __drm_fb_helper_initial_config_and_unlock(fb_helper, bpp_sel);
   1965
   1966	return ret;
   1967}
   1968EXPORT_SYMBOL(drm_fb_helper_initial_config);
   1969
   1970/**
   1971 * drm_fb_helper_hotplug_event - respond to a hotplug notification by
   1972 *                               probing all the outputs attached to the fb
   1973 * @fb_helper: driver-allocated fbdev helper, can be NULL
   1974 *
   1975 * Scan the connectors attached to the fb_helper and try to put together a
   1976 * setup after notification of a change in output configuration.
   1977 *
   1978 * Called at runtime, takes the mode config locks to be able to check/change the
   1979 * modeset configuration. Must be run from process context (which usually means
   1980 * either the output polling work or a work item launched from the driver's
   1981 * hotplug interrupt).
   1982 *
   1983 * Note that drivers may call this even before calling
   1984 * drm_fb_helper_initial_config but only after drm_fb_helper_init. This allows
   1985 * for a race-free fbcon setup and will make sure that the fbdev emulation will
   1986 * not miss any hotplug events.
   1987 *
   1988 * RETURNS:
   1989 * 0 on success and a non-zero error code otherwise.
   1990 */
   1991int drm_fb_helper_hotplug_event(struct drm_fb_helper *fb_helper)
   1992{
   1993	int err = 0;
   1994
   1995	if (!drm_fbdev_emulation || !fb_helper)
   1996		return 0;
   1997
   1998	mutex_lock(&fb_helper->lock);
   1999	if (fb_helper->deferred_setup) {
   2000		err = __drm_fb_helper_initial_config_and_unlock(fb_helper,
   2001				fb_helper->preferred_bpp);
   2002		return err;
   2003	}
   2004
   2005	if (!fb_helper->fb || !drm_master_internal_acquire(fb_helper->dev)) {
   2006		fb_helper->delayed_hotplug = true;
   2007		mutex_unlock(&fb_helper->lock);
   2008		return err;
   2009	}
   2010
   2011	drm_master_internal_release(fb_helper->dev);
   2012
   2013	drm_dbg_kms(fb_helper->dev, "\n");
   2014
   2015	drm_client_modeset_probe(&fb_helper->client, fb_helper->fb->width, fb_helper->fb->height);
   2016	drm_setup_crtcs_fb(fb_helper);
   2017	mutex_unlock(&fb_helper->lock);
   2018
   2019	drm_fb_helper_set_par(fb_helper->fbdev);
   2020
   2021	return 0;
   2022}
   2023EXPORT_SYMBOL(drm_fb_helper_hotplug_event);
   2024
   2025/**
   2026 * drm_fb_helper_lastclose - DRM driver lastclose helper for fbdev emulation
   2027 * @dev: DRM device
   2028 *
   2029 * This function can be used as the &drm_driver->lastclose callback for drivers
   2030 * that only need to call drm_fb_helper_restore_fbdev_mode_unlocked().
   2031 */
   2032void drm_fb_helper_lastclose(struct drm_device *dev)
   2033{
   2034	drm_fb_helper_restore_fbdev_mode_unlocked(dev->fb_helper);
   2035}
   2036EXPORT_SYMBOL(drm_fb_helper_lastclose);
   2037
   2038/**
   2039 * drm_fb_helper_output_poll_changed - DRM mode config \.output_poll_changed
   2040 *                                     helper for fbdev emulation
   2041 * @dev: DRM device
   2042 *
   2043 * This function can be used as the
   2044 * &drm_mode_config_funcs.output_poll_changed callback for drivers that only
   2045 * need to call drm_fb_helper_hotplug_event().
   2046 */
   2047void drm_fb_helper_output_poll_changed(struct drm_device *dev)
   2048{
   2049	drm_fb_helper_hotplug_event(dev->fb_helper);
   2050}
   2051EXPORT_SYMBOL(drm_fb_helper_output_poll_changed);
   2052
   2053/* @user: 1=userspace, 0=fbcon */
   2054static int drm_fbdev_fb_open(struct fb_info *info, int user)
   2055{
   2056	struct drm_fb_helper *fb_helper = info->par;
   2057
   2058	/* No need to take a ref for fbcon because it unbinds on unregister */
   2059	if (user && !try_module_get(fb_helper->dev->driver->fops->owner))
   2060		return -ENODEV;
   2061
   2062	return 0;
   2063}
   2064
   2065static int drm_fbdev_fb_release(struct fb_info *info, int user)
   2066{
   2067	struct drm_fb_helper *fb_helper = info->par;
   2068
   2069	if (user)
   2070		module_put(fb_helper->dev->driver->fops->owner);
   2071
   2072	return 0;
   2073}
   2074
   2075static void drm_fbdev_cleanup(struct drm_fb_helper *fb_helper)
   2076{
   2077	struct fb_info *fbi = fb_helper->fbdev;
   2078	void *shadow = NULL;
   2079
   2080	if (!fb_helper->dev)
   2081		return;
   2082
   2083	if (fbi) {
   2084		if (fbi->fbdefio)
   2085			fb_deferred_io_cleanup(fbi);
   2086		if (drm_fbdev_use_shadow_fb(fb_helper))
   2087			shadow = fbi->screen_buffer;
   2088	}
   2089
   2090	drm_fb_helper_fini(fb_helper);
   2091
   2092	if (shadow)
   2093		vfree(shadow);
   2094	else if (fb_helper->buffer)
   2095		drm_client_buffer_vunmap(fb_helper->buffer);
   2096
   2097	drm_client_framebuffer_delete(fb_helper->buffer);
   2098}
   2099
   2100static void drm_fbdev_release(struct drm_fb_helper *fb_helper)
   2101{
   2102	drm_fbdev_cleanup(fb_helper);
   2103	drm_client_release(&fb_helper->client);
   2104	kfree(fb_helper);
   2105}
   2106
   2107/*
   2108 * fb_ops.fb_destroy is called by the last put_fb_info() call at the end of
   2109 * unregister_framebuffer() or fb_release().
   2110 */
   2111static void drm_fbdev_fb_destroy(struct fb_info *info)
   2112{
   2113	drm_fbdev_release(info->par);
   2114}
   2115
   2116static int drm_fbdev_fb_mmap(struct fb_info *info, struct vm_area_struct *vma)
   2117{
   2118	struct drm_fb_helper *fb_helper = info->par;
   2119
   2120	if (drm_fbdev_use_shadow_fb(fb_helper))
   2121		return fb_deferred_io_mmap(info, vma);
   2122	else if (fb_helper->dev->driver->gem_prime_mmap)
   2123		return fb_helper->dev->driver->gem_prime_mmap(fb_helper->buffer->gem, vma);
   2124	else
   2125		return -ENODEV;
   2126}
   2127
   2128static bool drm_fbdev_use_iomem(struct fb_info *info)
   2129{
   2130	struct drm_fb_helper *fb_helper = info->par;
   2131	struct drm_client_buffer *buffer = fb_helper->buffer;
   2132
   2133	return !drm_fbdev_use_shadow_fb(fb_helper) && buffer->map.is_iomem;
   2134}
   2135
   2136static ssize_t fb_read_screen_base(struct fb_info *info, char __user *buf, size_t count,
   2137				   loff_t pos)
   2138{
   2139	const char __iomem *src = info->screen_base + pos;
   2140	size_t alloc_size = min_t(size_t, count, PAGE_SIZE);
   2141	ssize_t ret = 0;
   2142	int err = 0;
   2143	char *tmp;
   2144
   2145	tmp = kmalloc(alloc_size, GFP_KERNEL);
   2146	if (!tmp)
   2147		return -ENOMEM;
   2148
   2149	while (count) {
   2150		size_t c = min_t(size_t, count, alloc_size);
   2151
   2152		memcpy_fromio(tmp, src, c);
   2153		if (copy_to_user(buf, tmp, c)) {
   2154			err = -EFAULT;
   2155			break;
   2156		}
   2157
   2158		src += c;
   2159		buf += c;
   2160		ret += c;
   2161		count -= c;
   2162	}
   2163
   2164	kfree(tmp);
   2165
   2166	return ret ? ret : err;
   2167}
   2168
   2169static ssize_t fb_read_screen_buffer(struct fb_info *info, char __user *buf, size_t count,
   2170				     loff_t pos)
   2171{
   2172	const char *src = info->screen_buffer + pos;
   2173
   2174	if (copy_to_user(buf, src, count))
   2175		return -EFAULT;
   2176
   2177	return count;
   2178}
   2179
   2180static ssize_t drm_fbdev_fb_read(struct fb_info *info, char __user *buf,
   2181				 size_t count, loff_t *ppos)
   2182{
   2183	loff_t pos = *ppos;
   2184	size_t total_size;
   2185	ssize_t ret;
   2186
   2187	if (info->screen_size)
   2188		total_size = info->screen_size;
   2189	else
   2190		total_size = info->fix.smem_len;
   2191
   2192	if (pos >= total_size)
   2193		return 0;
   2194	if (count >= total_size)
   2195		count = total_size;
   2196	if (total_size - count < pos)
   2197		count = total_size - pos;
   2198
   2199	if (drm_fbdev_use_iomem(info))
   2200		ret = fb_read_screen_base(info, buf, count, pos);
   2201	else
   2202		ret = fb_read_screen_buffer(info, buf, count, pos);
   2203
   2204	if (ret > 0)
   2205		*ppos += ret;
   2206
   2207	return ret;
   2208}
   2209
   2210static ssize_t fb_write_screen_base(struct fb_info *info, const char __user *buf, size_t count,
   2211				    loff_t pos)
   2212{
   2213	char __iomem *dst = info->screen_base + pos;
   2214	size_t alloc_size = min_t(size_t, count, PAGE_SIZE);
   2215	ssize_t ret = 0;
   2216	int err = 0;
   2217	u8 *tmp;
   2218
   2219	tmp = kmalloc(alloc_size, GFP_KERNEL);
   2220	if (!tmp)
   2221		return -ENOMEM;
   2222
   2223	while (count) {
   2224		size_t c = min_t(size_t, count, alloc_size);
   2225
   2226		if (copy_from_user(tmp, buf, c)) {
   2227			err = -EFAULT;
   2228			break;
   2229		}
   2230		memcpy_toio(dst, tmp, c);
   2231
   2232		dst += c;
   2233		buf += c;
   2234		ret += c;
   2235		count -= c;
   2236	}
   2237
   2238	kfree(tmp);
   2239
   2240	return ret ? ret : err;
   2241}
   2242
   2243static ssize_t fb_write_screen_buffer(struct fb_info *info, const char __user *buf, size_t count,
   2244				      loff_t pos)
   2245{
   2246	char *dst = info->screen_buffer + pos;
   2247
   2248	if (copy_from_user(dst, buf, count))
   2249		return -EFAULT;
   2250
   2251	return count;
   2252}
   2253
   2254static ssize_t drm_fbdev_fb_write(struct fb_info *info, const char __user *buf,
   2255				  size_t count, loff_t *ppos)
   2256{
   2257	loff_t pos = *ppos;
   2258	size_t total_size;
   2259	ssize_t ret;
   2260	struct drm_rect damage_area;
   2261	int err = 0;
   2262
   2263	if (info->screen_size)
   2264		total_size = info->screen_size;
   2265	else
   2266		total_size = info->fix.smem_len;
   2267
   2268	if (pos > total_size)
   2269		return -EFBIG;
   2270	if (count > total_size) {
   2271		err = -EFBIG;
   2272		count = total_size;
   2273	}
   2274	if (total_size - count < pos) {
   2275		if (!err)
   2276			err = -ENOSPC;
   2277		count = total_size - pos;
   2278	}
   2279
   2280	/*
   2281	 * Copy to framebuffer even if we already logged an error. Emulates
   2282	 * the behavior of the original fbdev implementation.
   2283	 */
   2284	if (drm_fbdev_use_iomem(info))
   2285		ret = fb_write_screen_base(info, buf, count, pos);
   2286	else
   2287		ret = fb_write_screen_buffer(info, buf, count, pos);
   2288
   2289	if (ret < 0)
   2290		return ret; /* return last error, if any */
   2291	else if (!ret)
   2292		return err; /* return previous error, if any */
   2293
   2294	*ppos += ret;
   2295
   2296	drm_fb_helper_memory_range_to_clip(info, pos, ret, &damage_area);
   2297	drm_fb_helper_damage(info, damage_area.x1, damage_area.y1,
   2298			     drm_rect_width(&damage_area),
   2299			     drm_rect_height(&damage_area));
   2300
   2301	return ret;
   2302}
   2303
   2304static void drm_fbdev_fb_fillrect(struct fb_info *info,
   2305				  const struct fb_fillrect *rect)
   2306{
   2307	if (drm_fbdev_use_iomem(info))
   2308		drm_fb_helper_cfb_fillrect(info, rect);
   2309	else
   2310		drm_fb_helper_sys_fillrect(info, rect);
   2311}
   2312
   2313static void drm_fbdev_fb_copyarea(struct fb_info *info,
   2314				  const struct fb_copyarea *area)
   2315{
   2316	if (drm_fbdev_use_iomem(info))
   2317		drm_fb_helper_cfb_copyarea(info, area);
   2318	else
   2319		drm_fb_helper_sys_copyarea(info, area);
   2320}
   2321
   2322static void drm_fbdev_fb_imageblit(struct fb_info *info,
   2323				   const struct fb_image *image)
   2324{
   2325	if (drm_fbdev_use_iomem(info))
   2326		drm_fb_helper_cfb_imageblit(info, image);
   2327	else
   2328		drm_fb_helper_sys_imageblit(info, image);
   2329}
   2330
   2331static const struct fb_ops drm_fbdev_fb_ops = {
   2332	.owner		= THIS_MODULE,
   2333	DRM_FB_HELPER_DEFAULT_OPS,
   2334	.fb_open	= drm_fbdev_fb_open,
   2335	.fb_release	= drm_fbdev_fb_release,
   2336	.fb_destroy	= drm_fbdev_fb_destroy,
   2337	.fb_mmap	= drm_fbdev_fb_mmap,
   2338	.fb_read	= drm_fbdev_fb_read,
   2339	.fb_write	= drm_fbdev_fb_write,
   2340	.fb_fillrect	= drm_fbdev_fb_fillrect,
   2341	.fb_copyarea	= drm_fbdev_fb_copyarea,
   2342	.fb_imageblit	= drm_fbdev_fb_imageblit,
   2343};
   2344
   2345static struct fb_deferred_io drm_fbdev_defio = {
   2346	.delay		= HZ / 20,
   2347	.deferred_io	= drm_fb_helper_deferred_io,
   2348};
   2349
   2350/*
   2351 * This function uses the client API to create a framebuffer backed by a dumb buffer.
   2352 *
   2353 * The _sys_ versions are used for &fb_ops.fb_read, fb_write, fb_fillrect,
   2354 * fb_copyarea, fb_imageblit.
   2355 */
   2356static int drm_fb_helper_generic_probe(struct drm_fb_helper *fb_helper,
   2357				       struct drm_fb_helper_surface_size *sizes)
   2358{
   2359	struct drm_client_dev *client = &fb_helper->client;
   2360	struct drm_device *dev = fb_helper->dev;
   2361	struct drm_client_buffer *buffer;
   2362	struct drm_framebuffer *fb;
   2363	struct fb_info *fbi;
   2364	u32 format;
   2365	struct iosys_map map;
   2366	int ret;
   2367
   2368	drm_dbg_kms(dev, "surface width(%d), height(%d) and bpp(%d)\n",
   2369		    sizes->surface_width, sizes->surface_height,
   2370		    sizes->surface_bpp);
   2371
   2372	format = drm_mode_legacy_fb_format(sizes->surface_bpp, sizes->surface_depth);
   2373	buffer = drm_client_framebuffer_create(client, sizes->surface_width,
   2374					       sizes->surface_height, format);
   2375	if (IS_ERR(buffer))
   2376		return PTR_ERR(buffer);
   2377
   2378	fb_helper->buffer = buffer;
   2379	fb_helper->fb = buffer->fb;
   2380	fb = buffer->fb;
   2381
   2382	fbi = drm_fb_helper_alloc_fbi(fb_helper);
   2383	if (IS_ERR(fbi))
   2384		return PTR_ERR(fbi);
   2385
   2386	fbi->fbops = &drm_fbdev_fb_ops;
   2387	fbi->screen_size = sizes->surface_height * fb->pitches[0];
   2388	fbi->fix.smem_len = fbi->screen_size;
   2389	fbi->flags = FBINFO_DEFAULT;
   2390
   2391	drm_fb_helper_fill_info(fbi, fb_helper, sizes);
   2392
   2393	if (drm_fbdev_use_shadow_fb(fb_helper)) {
   2394		fbi->screen_buffer = vzalloc(fbi->screen_size);
   2395		if (!fbi->screen_buffer)
   2396			return -ENOMEM;
   2397		fbi->flags |= FBINFO_VIRTFB | FBINFO_READS_FAST;
   2398
   2399		fbi->fbdefio = &drm_fbdev_defio;
   2400		fb_deferred_io_init(fbi);
   2401	} else {
   2402		/* buffer is mapped for HW framebuffer */
   2403		ret = drm_client_buffer_vmap(fb_helper->buffer, &map);
   2404		if (ret)
   2405			return ret;
   2406		if (map.is_iomem) {
   2407			fbi->screen_base = map.vaddr_iomem;
   2408		} else {
   2409			fbi->screen_buffer = map.vaddr;
   2410			fbi->flags |= FBINFO_VIRTFB;
   2411		}
   2412
   2413		/*
   2414		 * Shamelessly leak the physical address to user-space. As
   2415		 * page_to_phys() is undefined for I/O memory, warn in this
   2416		 * case.
   2417		 */
   2418#if IS_ENABLED(CONFIG_DRM_FBDEV_LEAK_PHYS_SMEM)
   2419		if (drm_leak_fbdev_smem && fbi->fix.smem_start == 0 &&
   2420		    !drm_WARN_ON_ONCE(dev, map.is_iomem))
   2421			fbi->fix.smem_start =
   2422				page_to_phys(virt_to_page(fbi->screen_buffer));
   2423#endif
   2424	}
   2425
   2426	return 0;
   2427}
   2428
   2429static const struct drm_fb_helper_funcs drm_fb_helper_generic_funcs = {
   2430	.fb_probe = drm_fb_helper_generic_probe,
   2431};
   2432
   2433static void drm_fbdev_client_unregister(struct drm_client_dev *client)
   2434{
   2435	struct drm_fb_helper *fb_helper = drm_fb_helper_from_client(client);
   2436
   2437	if (fb_helper->fbdev)
   2438		/* drm_fbdev_fb_destroy() takes care of cleanup */
   2439		drm_fb_helper_unregister_fbi(fb_helper);
   2440	else
   2441		drm_fbdev_release(fb_helper);
   2442}
   2443
   2444static int drm_fbdev_client_restore(struct drm_client_dev *client)
   2445{
   2446	drm_fb_helper_lastclose(client->dev);
   2447
   2448	return 0;
   2449}
   2450
   2451static int drm_fbdev_client_hotplug(struct drm_client_dev *client)
   2452{
   2453	struct drm_fb_helper *fb_helper = drm_fb_helper_from_client(client);
   2454	struct drm_device *dev = client->dev;
   2455	int ret;
   2456
   2457	/* Setup is not retried if it has failed */
   2458	if (!fb_helper->dev && fb_helper->funcs)
   2459		return 0;
   2460
   2461	if (dev->fb_helper)
   2462		return drm_fb_helper_hotplug_event(dev->fb_helper);
   2463
   2464	if (!dev->mode_config.num_connector) {
   2465		drm_dbg_kms(dev, "No connectors found, will not create framebuffer!\n");
   2466		return 0;
   2467	}
   2468
   2469	drm_fb_helper_prepare(dev, fb_helper, &drm_fb_helper_generic_funcs);
   2470
   2471	ret = drm_fb_helper_init(dev, fb_helper);
   2472	if (ret)
   2473		goto err;
   2474
   2475	if (!drm_drv_uses_atomic_modeset(dev))
   2476		drm_helper_disable_unused_functions(dev);
   2477
   2478	ret = drm_fb_helper_initial_config(fb_helper, fb_helper->preferred_bpp);
   2479	if (ret)
   2480		goto err_cleanup;
   2481
   2482	return 0;
   2483
   2484err_cleanup:
   2485	drm_fbdev_cleanup(fb_helper);
   2486err:
   2487	fb_helper->dev = NULL;
   2488	fb_helper->fbdev = NULL;
   2489
   2490	drm_err(dev, "fbdev: Failed to setup generic emulation (ret=%d)\n", ret);
   2491
   2492	return ret;
   2493}
   2494
   2495static const struct drm_client_funcs drm_fbdev_client_funcs = {
   2496	.owner		= THIS_MODULE,
   2497	.unregister	= drm_fbdev_client_unregister,
   2498	.restore	= drm_fbdev_client_restore,
   2499	.hotplug	= drm_fbdev_client_hotplug,
   2500};
   2501
   2502/**
   2503 * drm_fbdev_generic_setup() - Setup generic fbdev emulation
   2504 * @dev: DRM device
   2505 * @preferred_bpp: Preferred bits per pixel for the device.
   2506 *                 @dev->mode_config.preferred_depth is used if this is zero.
   2507 *
   2508 * This function sets up generic fbdev emulation for drivers that supports
   2509 * dumb buffers with a virtual address and that can be mmap'ed.
   2510 * drm_fbdev_generic_setup() shall be called after the DRM driver registered
   2511 * the new DRM device with drm_dev_register().
   2512 *
   2513 * Restore, hotplug events and teardown are all taken care of. Drivers that do
   2514 * suspend/resume need to call drm_fb_helper_set_suspend_unlocked() themselves.
   2515 * Simple drivers might use drm_mode_config_helper_suspend().
   2516 *
   2517 * Drivers that set the dirty callback on their framebuffer will get a shadow
   2518 * fbdev buffer that is blitted onto the real buffer. This is done in order to
   2519 * make deferred I/O work with all kinds of buffers. A shadow buffer can be
   2520 * requested explicitly by setting struct drm_mode_config.prefer_shadow or
   2521 * struct drm_mode_config.prefer_shadow_fbdev to true beforehand. This is
   2522 * required to use generic fbdev emulation with SHMEM helpers.
   2523 *
   2524 * This function is safe to call even when there are no connectors present.
   2525 * Setup will be retried on the next hotplug event.
   2526 *
   2527 * The fbdev is destroyed by drm_dev_unregister().
   2528 */
   2529void drm_fbdev_generic_setup(struct drm_device *dev,
   2530			     unsigned int preferred_bpp)
   2531{
   2532	struct drm_fb_helper *fb_helper;
   2533	int ret;
   2534
   2535	drm_WARN(dev, !dev->registered, "Device has not been registered.\n");
   2536	drm_WARN(dev, dev->fb_helper, "fb_helper is already set!\n");
   2537
   2538	if (!drm_fbdev_emulation)
   2539		return;
   2540
   2541	fb_helper = kzalloc(sizeof(*fb_helper), GFP_KERNEL);
   2542	if (!fb_helper) {
   2543		drm_err(dev, "Failed to allocate fb_helper\n");
   2544		return;
   2545	}
   2546
   2547	ret = drm_client_init(dev, &fb_helper->client, "fbdev", &drm_fbdev_client_funcs);
   2548	if (ret) {
   2549		kfree(fb_helper);
   2550		drm_err(dev, "Failed to register client: %d\n", ret);
   2551		return;
   2552	}
   2553
   2554	/*
   2555	 * FIXME: This mixes up depth with bpp, which results in a glorious
   2556	 * mess, resulting in some drivers picking wrong fbdev defaults and
   2557	 * others wrong preferred_depth defaults.
   2558	 */
   2559	if (!preferred_bpp)
   2560		preferred_bpp = dev->mode_config.preferred_depth;
   2561	if (!preferred_bpp)
   2562		preferred_bpp = 32;
   2563	fb_helper->preferred_bpp = preferred_bpp;
   2564
   2565	ret = drm_fbdev_client_hotplug(&fb_helper->client);
   2566	if (ret)
   2567		drm_dbg_kms(dev, "client hotplug ret=%d\n", ret);
   2568
   2569	drm_client_register(&fb_helper->client);
   2570}
   2571EXPORT_SYMBOL(drm_fbdev_generic_setup);