Home | History | Annotate | Line # | Download | only in amdgpu
      1  1.11       chs /*	$NetBSD: amdgpu_fb.c,v 1.11 2021/12/20 20:34:58 chs Exp $	*/
      2   1.1  riastrad 
      3   1.1  riastrad /*
      4   1.1  riastrad  * Copyright  2007 David Airlie
      5   1.1  riastrad  *
      6   1.1  riastrad  * Permission is hereby granted, free of charge, to any person obtaining a
      7   1.1  riastrad  * copy of this software and associated documentation files (the "Software"),
      8   1.1  riastrad  * to deal in the Software without restriction, including without limitation
      9   1.1  riastrad  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
     10   1.1  riastrad  * and/or sell copies of the Software, and to permit persons to whom the
     11   1.1  riastrad  * Software is furnished to do so, subject to the following conditions:
     12   1.1  riastrad  *
     13   1.1  riastrad  * The above copyright notice and this permission notice (including the next
     14   1.1  riastrad  * paragraph) shall be included in all copies or substantial portions of the
     15   1.1  riastrad  * Software.
     16   1.1  riastrad  *
     17   1.1  riastrad  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     18   1.1  riastrad  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     19   1.1  riastrad  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
     20   1.1  riastrad  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     21   1.1  riastrad  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
     22   1.1  riastrad  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
     23   1.1  riastrad  * DEALINGS IN THE SOFTWARE.
     24   1.1  riastrad  *
     25   1.1  riastrad  * Authors:
     26   1.1  riastrad  *     David Airlie
     27   1.1  riastrad  */
     28   1.8  riastrad 
     29   1.1  riastrad #include <sys/cdefs.h>
     30  1.11       chs __KERNEL_RCSID(0, "$NetBSD: amdgpu_fb.c,v 1.11 2021/12/20 20:34:58 chs Exp $");
     31   1.1  riastrad 
     32   1.1  riastrad #include <linux/module.h>
     33   1.8  riastrad #include <linux/pm_runtime.h>
     34   1.1  riastrad #include <linux/slab.h>
     35   1.8  riastrad #include <linux/vga_switcheroo.h>
     36   1.1  riastrad 
     37   1.8  riastrad #include <drm/amdgpu_drm.h>
     38   1.1  riastrad #include <drm/drm_crtc.h>
     39   1.1  riastrad #include <drm/drm_crtc_helper.h>
     40   1.8  riastrad #include <drm/drm_fb_helper.h>
     41   1.8  riastrad #include <drm/drm_fourcc.h>
     42   1.8  riastrad 
     43   1.1  riastrad #include "amdgpu.h"
     44   1.1  riastrad #include "cikd.h"
     45   1.8  riastrad #include "amdgpu_gem.h"
     46   1.1  riastrad 
     47   1.8  riastrad #include "amdgpu_display.h"
     48   1.1  riastrad 
     49   1.3  riastrad #ifdef __NetBSD__
     50   1.3  riastrad #include "amdgpufb.h"
     51   1.3  riastrad #endif
     52   1.3  riastrad 
     53   1.4  riastrad #include <linux/nbsd-namespace.h>
     54   1.4  riastrad 
     55   1.1  riastrad /* object hierarchy -
     56   1.1  riastrad    this contains a helper + a amdgpu fb
     57   1.1  riastrad    the helper contains a pointer to amdgpu framebuffer baseclass.
     58   1.1  riastrad */
     59   1.8  riastrad 
     60  1.10  riastrad #ifndef __NetBSD__
     61  1.10  riastrad 
     62   1.8  riastrad static int
     63   1.8  riastrad amdgpufb_open(struct fb_info *info, int user)
     64   1.8  riastrad {
     65   1.8  riastrad 	struct drm_fb_helper *fb_helper = info->par;
     66   1.8  riastrad 	int ret = pm_runtime_get_sync(fb_helper->dev->dev);
     67   1.8  riastrad 	if (ret < 0 && ret != -EACCES) {
     68   1.8  riastrad 		pm_runtime_mark_last_busy(fb_helper->dev->dev);
     69   1.8  riastrad 		pm_runtime_put_autosuspend(fb_helper->dev->dev);
     70   1.8  riastrad 		return ret;
     71   1.8  riastrad 	}
     72   1.8  riastrad 	return 0;
     73   1.8  riastrad }
     74   1.8  riastrad 
     75   1.8  riastrad static int
     76   1.8  riastrad amdgpufb_release(struct fb_info *info, int user)
     77   1.8  riastrad {
     78   1.8  riastrad 	struct drm_fb_helper *fb_helper = info->par;
     79   1.8  riastrad 
     80   1.8  riastrad 	pm_runtime_mark_last_busy(fb_helper->dev->dev);
     81   1.8  riastrad 	pm_runtime_put_autosuspend(fb_helper->dev->dev);
     82   1.8  riastrad 	return 0;
     83   1.8  riastrad }
     84   1.1  riastrad 
     85   1.8  riastrad static const struct fb_ops amdgpufb_ops = {
     86   1.1  riastrad 	.owner = THIS_MODULE,
     87   1.8  riastrad 	DRM_FB_HELPER_DEFAULT_OPS,
     88   1.8  riastrad 	.fb_open = amdgpufb_open,
     89   1.8  riastrad 	.fb_release = amdgpufb_release,
     90   1.1  riastrad 	.fb_fillrect = drm_fb_helper_cfb_fillrect,
     91   1.1  riastrad 	.fb_copyarea = drm_fb_helper_cfb_copyarea,
     92   1.1  riastrad 	.fb_imageblit = drm_fb_helper_cfb_imageblit,
     93   1.1  riastrad };
     94  1.10  riastrad 
     95   1.3  riastrad #endif
     96   1.1  riastrad 
     97   1.1  riastrad 
     98   1.8  riastrad int amdgpu_align_pitch(struct amdgpu_device *adev, int width, int cpp, bool tiled)
     99   1.1  riastrad {
    100   1.1  riastrad 	int aligned = width;
    101   1.1  riastrad 	int pitch_mask = 0;
    102   1.1  riastrad 
    103   1.8  riastrad 	switch (cpp) {
    104   1.1  riastrad 	case 1:
    105   1.1  riastrad 		pitch_mask = 255;
    106   1.1  riastrad 		break;
    107   1.1  riastrad 	case 2:
    108   1.1  riastrad 		pitch_mask = 127;
    109   1.1  riastrad 		break;
    110   1.1  riastrad 	case 3:
    111   1.1  riastrad 	case 4:
    112   1.1  riastrad 		pitch_mask = 63;
    113   1.1  riastrad 		break;
    114   1.1  riastrad 	}
    115   1.1  riastrad 
    116   1.1  riastrad 	aligned += pitch_mask;
    117   1.1  riastrad 	aligned &= ~pitch_mask;
    118   1.8  riastrad 	return aligned * cpp;
    119   1.1  riastrad }
    120   1.1  riastrad 
    121   1.1  riastrad static void amdgpufb_destroy_pinned_object(struct drm_gem_object *gobj)
    122   1.1  riastrad {
    123   1.8  riastrad 	struct amdgpu_bo *abo = gem_to_amdgpu_bo(gobj);
    124   1.1  riastrad 	int ret;
    125   1.1  riastrad 
    126   1.8  riastrad 	ret = amdgpu_bo_reserve(abo, true);
    127   1.1  riastrad 	if (likely(ret == 0)) {
    128   1.8  riastrad 		amdgpu_bo_kunmap(abo);
    129   1.8  riastrad 		amdgpu_bo_unpin(abo);
    130   1.8  riastrad 		amdgpu_bo_unreserve(abo);
    131   1.1  riastrad 	}
    132   1.8  riastrad 	drm_gem_object_put_unlocked(gobj);
    133   1.1  riastrad }
    134   1.1  riastrad 
    135   1.1  riastrad static int amdgpufb_create_pinned_object(struct amdgpu_fbdev *rfbdev,
    136   1.1  riastrad 					 struct drm_mode_fb_cmd2 *mode_cmd,
    137   1.1  riastrad 					 struct drm_gem_object **gobj_p)
    138   1.1  riastrad {
    139   1.8  riastrad 	const struct drm_format_info *info;
    140   1.1  riastrad 	struct amdgpu_device *adev = rfbdev->adev;
    141   1.1  riastrad 	struct drm_gem_object *gobj = NULL;
    142   1.8  riastrad 	struct amdgpu_bo *abo = NULL;
    143   1.1  riastrad 	bool fb_tiled = false; /* useful for testing */
    144   1.8  riastrad 	u32 tiling_flags = 0, domain;
    145   1.1  riastrad 	int ret;
    146   1.1  riastrad 	int aligned_size, size;
    147   1.1  riastrad 	int height = mode_cmd->height;
    148   1.8  riastrad 	u32 cpp;
    149   1.8  riastrad 	u64 flags = AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED |
    150   1.8  riastrad 			       AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS     |
    151   1.8  riastrad 			       AMDGPU_GEM_CREATE_VRAM_CLEARED 	     |
    152   1.8  riastrad 			       AMDGPU_GEM_CREATE_CPU_GTT_USWC;
    153   1.1  riastrad 
    154   1.8  riastrad 	info = drm_get_format_info(adev->ddev, mode_cmd);
    155   1.8  riastrad 	cpp = info->cpp[0];
    156   1.1  riastrad 
    157   1.1  riastrad 	/* need to align pitch with crtc limits */
    158   1.8  riastrad 	mode_cmd->pitches[0] = amdgpu_align_pitch(adev, mode_cmd->width, cpp,
    159   1.8  riastrad 						  fb_tiled);
    160   1.8  riastrad 	domain = amdgpu_display_supported_domains(adev, flags);
    161   1.1  riastrad 	height = ALIGN(mode_cmd->height, 8);
    162   1.1  riastrad 	size = mode_cmd->pitches[0] * height;
    163   1.1  riastrad 	aligned_size = ALIGN(size, PAGE_SIZE);
    164   1.8  riastrad 	ret = amdgpu_gem_object_create(adev, aligned_size, 0, domain, flags,
    165   1.8  riastrad 				       ttm_bo_type_kernel, NULL, &gobj);
    166   1.1  riastrad 	if (ret) {
    167   1.8  riastrad 		pr_err("failed to allocate framebuffer (%d)\n", aligned_size);
    168   1.1  riastrad 		return -ENOMEM;
    169   1.1  riastrad 	}
    170   1.8  riastrad 	abo = gem_to_amdgpu_bo(gobj);
    171   1.1  riastrad 
    172   1.1  riastrad 	if (fb_tiled)
    173   1.1  riastrad 		tiling_flags = AMDGPU_TILING_SET(ARRAY_MODE, GRPH_ARRAY_2D_TILED_THIN1);
    174   1.1  riastrad 
    175   1.8  riastrad 	ret = amdgpu_bo_reserve(abo, false);
    176   1.1  riastrad 	if (unlikely(ret != 0))
    177   1.1  riastrad 		goto out_unref;
    178   1.1  riastrad 
    179   1.1  riastrad 	if (tiling_flags) {
    180   1.8  riastrad 		ret = amdgpu_bo_set_tiling_flags(abo,
    181   1.1  riastrad 						 tiling_flags);
    182   1.1  riastrad 		if (ret)
    183   1.1  riastrad 			dev_err(adev->dev, "FB failed to set tiling flags\n");
    184   1.1  riastrad 	}
    185   1.1  riastrad 
    186   1.8  riastrad 	ret = amdgpu_bo_pin(abo, domain);
    187   1.8  riastrad 	if (ret) {
    188   1.8  riastrad 		amdgpu_bo_unreserve(abo);
    189   1.8  riastrad 		goto out_unref;
    190   1.8  riastrad 	}
    191   1.1  riastrad 
    192   1.8  riastrad 	ret = amdgpu_ttm_alloc_gart(&abo->tbo);
    193   1.1  riastrad 	if (ret) {
    194   1.8  riastrad 		amdgpu_bo_unreserve(abo);
    195   1.8  riastrad 		dev_err(adev->dev, "%p bind failed\n", abo);
    196   1.1  riastrad 		goto out_unref;
    197   1.1  riastrad 	}
    198   1.8  riastrad 
    199   1.8  riastrad 	ret = amdgpu_bo_kmap(abo, NULL);
    200   1.8  riastrad 	amdgpu_bo_unreserve(abo);
    201   1.1  riastrad 	if (ret) {
    202   1.1  riastrad 		goto out_unref;
    203   1.1  riastrad 	}
    204   1.1  riastrad 
    205   1.1  riastrad 	*gobj_p = gobj;
    206   1.1  riastrad 	return 0;
    207   1.1  riastrad out_unref:
    208   1.1  riastrad 	amdgpufb_destroy_pinned_object(gobj);
    209   1.1  riastrad 	*gobj_p = NULL;
    210   1.1  riastrad 	return ret;
    211   1.1  riastrad }
    212   1.1  riastrad 
    213   1.1  riastrad static int amdgpufb_create(struct drm_fb_helper *helper,
    214   1.1  riastrad 			   struct drm_fb_helper_surface_size *sizes)
    215   1.1  riastrad {
    216   1.1  riastrad 	struct amdgpu_fbdev *rfbdev = (struct amdgpu_fbdev *)helper;
    217   1.1  riastrad 	struct amdgpu_device *adev = rfbdev->adev;
    218   1.1  riastrad 	struct fb_info *info;
    219   1.1  riastrad 	struct drm_framebuffer *fb = NULL;
    220   1.1  riastrad 	struct drm_mode_fb_cmd2 mode_cmd;
    221   1.1  riastrad 	struct drm_gem_object *gobj = NULL;
    222   1.8  riastrad 	struct amdgpu_bo *abo = NULL;
    223   1.1  riastrad 	int ret;
    224   1.1  riastrad 	unsigned long tmp;
    225   1.1  riastrad 
    226   1.1  riastrad 	mode_cmd.width = sizes->surface_width;
    227   1.1  riastrad 	mode_cmd.height = sizes->surface_height;
    228   1.1  riastrad 
    229   1.1  riastrad 	if (sizes->surface_bpp == 24)
    230   1.1  riastrad 		sizes->surface_bpp = 32;
    231   1.1  riastrad 
    232   1.1  riastrad 	mode_cmd.pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp,
    233   1.1  riastrad 							  sizes->surface_depth);
    234   1.1  riastrad 
    235   1.1  riastrad 	ret = amdgpufb_create_pinned_object(rfbdev, &mode_cmd, &gobj);
    236   1.1  riastrad 	if (ret) {
    237   1.1  riastrad 		DRM_ERROR("failed to create fbcon object %d\n", ret);
    238   1.1  riastrad 		return ret;
    239   1.1  riastrad 	}
    240   1.1  riastrad 
    241   1.8  riastrad 	abo = gem_to_amdgpu_bo(gobj);
    242   1.1  riastrad 
    243  1.10  riastrad #ifndef __NetBSD__
    244  1.10  riastrad 	/* okay we have an object now allocate the framebuffer */
    245  1.10  riastrad 	info = drm_fb_helper_alloc_fbi(helper);
    246  1.10  riastrad 	if (IS_ERR(info)) {
    247  1.10  riastrad 		ret = PTR_ERR(info);
    248  1.10  riastrad 		goto out;
    249  1.10  riastrad 	}
    250  1.10  riastrad #endif
    251  1.10  riastrad 
    252  1.10  riastrad 	ret = amdgpu_display_framebuffer_init(adev->ddev, &rfbdev->rfb,
    253  1.10  riastrad 					      &mode_cmd, gobj);
    254   1.3  riastrad 	if (ret) {
    255   1.3  riastrad 		DRM_ERROR("failed to initialize framebuffer %d\n", ret);
    256  1.10  riastrad 		goto out;
    257   1.3  riastrad 	}
    258   1.3  riastrad 
    259  1.10  riastrad 	fb = &rfbdev->rfb.base;
    260  1.10  riastrad 
    261  1.10  riastrad 	/* setup helper */
    262  1.10  riastrad 	rfbdev->helper.fb = fb;
    263   1.3  riastrad 
    264  1.10  riastrad #ifdef __NetBSD__
    265   1.3  riastrad     {
    266   1.3  riastrad 	static const struct amdgpufb_attach_args zero_afa;
    267   1.3  riastrad 	struct amdgpufb_attach_args afa = zero_afa;
    268   1.3  riastrad 
    269  1.10  riastrad 	__USE(tmp);
    270  1.10  riastrad 	__USE(info);
    271  1.10  riastrad 
    272   1.3  riastrad 	afa.afa_fb_helper = helper;
    273   1.3  riastrad 	afa.afa_fb_sizes = *sizes;
    274  1.10  riastrad 	afa.afa_fb_ptr = amdgpu_bo_kptr(abo);
    275   1.3  riastrad 	afa.afa_fb_linebytes = mode_cmd.pitches[0];
    276   1.3  riastrad 
    277  1.11       chs 	KERNEL_LOCK(1, NULL);
    278   1.6   thorpej 	helper->fbdev = config_found(adev->ddev->dev, &afa, NULL,
    279   1.7   thorpej 	    CFARGS(.iattr = "amdgpufbbus"));
    280  1.11       chs 	KERNEL_UNLOCK_ONE(NULL);
    281   1.3  riastrad 	if (helper->fbdev == NULL) {
    282   1.3  riastrad 		DRM_ERROR("failed to attach amdgpufb\n");
    283  1.10  riastrad 		goto out;
    284   1.3  riastrad 	}
    285   1.3  riastrad     }
    286   1.3  riastrad #else  /* __NetBSD__ */
    287   1.1  riastrad 	info->fbops = &amdgpufb_ops;
    288   1.1  riastrad 
    289   1.8  riastrad 	tmp = amdgpu_bo_gpu_offset(abo) - adev->gmc.vram_start;
    290   1.8  riastrad 	info->fix.smem_start = adev->gmc.aper_base + tmp;
    291   1.8  riastrad 	info->fix.smem_len = amdgpu_bo_size(abo);
    292   1.8  riastrad 	info->screen_base = amdgpu_bo_kptr(abo);
    293   1.8  riastrad 	info->screen_size = amdgpu_bo_size(abo);
    294   1.1  riastrad 
    295   1.8  riastrad 	drm_fb_helper_fill_info(info, &rfbdev->helper, sizes);
    296   1.1  riastrad 
    297   1.1  riastrad 	/* setup aperture base/size for vesafb takeover */
    298   1.1  riastrad 	info->apertures->ranges[0].base = adev->ddev->mode_config.fb_base;
    299   1.8  riastrad 	info->apertures->ranges[0].size = adev->gmc.aper_size;
    300   1.1  riastrad 
    301   1.1  riastrad 	/* Use default scratch pixmap (info->pixmap.flags = FB_PIXMAP_SYSTEM) */
    302   1.1  riastrad 
    303   1.1  riastrad 	if (info->screen_base == NULL) {
    304   1.1  riastrad 		ret = -ENOSPC;
    305   1.8  riastrad 		goto out;
    306   1.1  riastrad 	}
    307   1.1  riastrad 
    308   1.1  riastrad 	DRM_INFO("fb mappable at 0x%lX\n",  info->fix.smem_start);
    309   1.8  riastrad 	DRM_INFO("vram apper at 0x%lX\n",  (unsigned long)adev->gmc.aper_base);
    310   1.8  riastrad 	DRM_INFO("size %lu\n", (unsigned long)amdgpu_bo_size(abo));
    311   1.8  riastrad 	DRM_INFO("fb depth is %d\n", fb->format->depth);
    312   1.1  riastrad 	DRM_INFO("   pitch is %d\n", fb->pitches[0]);
    313   1.1  riastrad 
    314   1.1  riastrad 	vga_switcheroo_client_fb_set(adev->ddev->pdev, info);
    315   1.3  riastrad #endif
    316   1.1  riastrad 	return 0;
    317   1.1  riastrad 
    318   1.8  riastrad out:
    319   1.8  riastrad 	if (abo) {
    320   1.1  riastrad 
    321   1.1  riastrad 	}
    322   1.1  riastrad 	if (fb && ret) {
    323   1.8  riastrad 		drm_gem_object_put_unlocked(gobj);
    324   1.1  riastrad 		drm_framebuffer_unregister_private(fb);
    325   1.1  riastrad 		drm_framebuffer_cleanup(fb);
    326   1.1  riastrad 		kfree(fb);
    327   1.1  riastrad 	}
    328   1.1  riastrad 	return ret;
    329   1.1  riastrad }
    330   1.1  riastrad 
    331   1.1  riastrad static int amdgpu_fbdev_destroy(struct drm_device *dev, struct amdgpu_fbdev *rfbdev)
    332   1.1  riastrad {
    333   1.1  riastrad 	struct amdgpu_framebuffer *rfb = &rfbdev->rfb;
    334   1.1  riastrad 
    335   1.1  riastrad 	drm_fb_helper_unregister_fbi(&rfbdev->helper);
    336   1.1  riastrad 
    337   1.8  riastrad 	if (rfb->base.obj[0]) {
    338   1.8  riastrad 		amdgpufb_destroy_pinned_object(rfb->base.obj[0]);
    339   1.8  riastrad 		rfb->base.obj[0] = NULL;
    340   1.8  riastrad 		drm_framebuffer_unregister_private(&rfb->base);
    341   1.8  riastrad 		drm_framebuffer_cleanup(&rfb->base);
    342   1.1  riastrad 	}
    343   1.1  riastrad 	drm_fb_helper_fini(&rfbdev->helper);
    344   1.1  riastrad 
    345   1.1  riastrad 	return 0;
    346   1.1  riastrad }
    347   1.1  riastrad 
    348   1.1  riastrad static const struct drm_fb_helper_funcs amdgpu_fb_helper_funcs = {
    349   1.1  riastrad 	.fb_probe = amdgpufb_create,
    350   1.1  riastrad };
    351   1.1  riastrad 
    352   1.1  riastrad int amdgpu_fbdev_init(struct amdgpu_device *adev)
    353   1.1  riastrad {
    354   1.1  riastrad 	struct amdgpu_fbdev *rfbdev;
    355   1.1  riastrad 	int bpp_sel = 32;
    356   1.1  riastrad 	int ret;
    357   1.1  riastrad 
    358   1.1  riastrad 	/* don't init fbdev on hw without DCE */
    359   1.1  riastrad 	if (!adev->mode_info.mode_config_initialized)
    360   1.1  riastrad 		return 0;
    361   1.1  riastrad 
    362   1.8  riastrad 	/* don't init fbdev if there are no connectors */
    363   1.8  riastrad 	if (list_empty(&adev->ddev->mode_config.connector_list))
    364   1.8  riastrad 		return 0;
    365   1.8  riastrad 
    366   1.1  riastrad 	/* select 8 bpp console on low vram cards */
    367   1.8  riastrad 	if (adev->gmc.real_vram_size <= (32*1024*1024))
    368   1.1  riastrad 		bpp_sel = 8;
    369   1.1  riastrad 
    370   1.1  riastrad 	rfbdev = kzalloc(sizeof(struct amdgpu_fbdev), GFP_KERNEL);
    371   1.1  riastrad 	if (!rfbdev)
    372   1.1  riastrad 		return -ENOMEM;
    373   1.1  riastrad 
    374   1.1  riastrad 	rfbdev->adev = adev;
    375   1.1  riastrad 	adev->mode_info.rfbdev = rfbdev;
    376   1.1  riastrad 
    377   1.1  riastrad 	drm_fb_helper_prepare(adev->ddev, &rfbdev->helper,
    378   1.1  riastrad 			&amdgpu_fb_helper_funcs);
    379   1.1  riastrad 
    380   1.1  riastrad 	ret = drm_fb_helper_init(adev->ddev, &rfbdev->helper,
    381   1.1  riastrad 				 AMDGPUFB_CONN_LIMIT);
    382   1.1  riastrad 	if (ret) {
    383   1.1  riastrad 		kfree(rfbdev);
    384   1.1  riastrad 		return ret;
    385   1.1  riastrad 	}
    386   1.1  riastrad 
    387   1.1  riastrad 	drm_fb_helper_single_add_all_connectors(&rfbdev->helper);
    388   1.1  riastrad 
    389   1.1  riastrad 	/* disable all the possible outputs/crtcs before entering KMS mode */
    390   1.8  riastrad 	if (!amdgpu_device_has_dc_support(adev))
    391   1.8  riastrad 		drm_helper_disable_unused_functions(adev->ddev);
    392   1.1  riastrad 
    393   1.1  riastrad 	drm_fb_helper_initial_config(&rfbdev->helper, bpp_sel);
    394   1.1  riastrad 	return 0;
    395   1.1  riastrad }
    396   1.1  riastrad 
    397   1.1  riastrad void amdgpu_fbdev_fini(struct amdgpu_device *adev)
    398   1.1  riastrad {
    399   1.1  riastrad 	if (!adev->mode_info.rfbdev)
    400   1.1  riastrad 		return;
    401   1.1  riastrad 
    402   1.1  riastrad 	amdgpu_fbdev_destroy(adev->ddev, adev->mode_info.rfbdev);
    403   1.1  riastrad 	kfree(adev->mode_info.rfbdev);
    404   1.1  riastrad 	adev->mode_info.rfbdev = NULL;
    405   1.1  riastrad }
    406   1.1  riastrad 
    407   1.1  riastrad void amdgpu_fbdev_set_suspend(struct amdgpu_device *adev, int state)
    408   1.1  riastrad {
    409   1.1  riastrad 	if (adev->mode_info.rfbdev)
    410   1.8  riastrad 		drm_fb_helper_set_suspend_unlocked(&adev->mode_info.rfbdev->helper,
    411   1.8  riastrad 						   state);
    412   1.1  riastrad }
    413   1.1  riastrad 
    414   1.1  riastrad int amdgpu_fbdev_total_size(struct amdgpu_device *adev)
    415   1.1  riastrad {
    416   1.1  riastrad 	struct amdgpu_bo *robj;
    417   1.1  riastrad 	int size = 0;
    418   1.1  riastrad 
    419   1.1  riastrad 	if (!adev->mode_info.rfbdev)
    420   1.1  riastrad 		return 0;
    421   1.1  riastrad 
    422   1.8  riastrad 	robj = gem_to_amdgpu_bo(adev->mode_info.rfbdev->rfb.base.obj[0]);
    423   1.1  riastrad 	size += amdgpu_bo_size(robj);
    424   1.1  riastrad 	return size;
    425   1.1  riastrad }
    426   1.1  riastrad 
    427   1.1  riastrad bool amdgpu_fbdev_robj_is_fb(struct amdgpu_device *adev, struct amdgpu_bo *robj)
    428   1.1  riastrad {
    429   1.1  riastrad 	if (!adev->mode_info.rfbdev)
    430   1.1  riastrad 		return false;
    431   1.8  riastrad 	if (robj == gem_to_amdgpu_bo(adev->mode_info.rfbdev->rfb.base.obj[0]))
    432   1.1  riastrad 		return true;
    433   1.1  riastrad 	return false;
    434   1.1  riastrad }
    435