LCOV - code coverage report
Current view: top level - drivers/gpu/drm/amd/amdgpu - amdgpu_vkms.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 233 0.0 %
Date: 2022-12-09 01:23:36 Functions: 0 26 0.0 %

          Line data    Source code
       1             : // SPDX-License-Identifier: GPL-2.0+
       2             : 
       3             : #include <drm/drm_atomic_helper.h>
       4             : #include <drm/drm_simple_kms_helper.h>
       5             : #include <drm/drm_vblank.h>
       6             : 
       7             : #include "amdgpu.h"
       8             : #ifdef CONFIG_DRM_AMDGPU_SI
       9             : #include "dce_v6_0.h"
      10             : #endif
      11             : #ifdef CONFIG_DRM_AMDGPU_CIK
      12             : #include "dce_v8_0.h"
      13             : #endif
      14             : #include "dce_v10_0.h"
      15             : #include "dce_v11_0.h"
      16             : #include "ivsrcid/ivsrcid_vislands30.h"
      17             : #include "amdgpu_vkms.h"
      18             : #include "amdgpu_display.h"
      19             : #include "atom.h"
      20             : #include "amdgpu_irq.h"
      21             : 
      22             : /**
      23             :  * DOC: amdgpu_vkms
      24             :  *
      25             :  * The amdgpu vkms interface provides a virtual KMS interface for several use
      26             :  * cases: devices without display hardware, platforms where the actual display
      27             :  * hardware is not useful (e.g., servers), SR-IOV virtual functions, device
      28             :  * emulation/simulation, and device bring up prior to display hardware being
      29             :  * usable. We previously emulated a legacy KMS interface, but there was a desire
      30             :  * to move to the atomic KMS interface. The vkms driver did everything we
      31             :  * needed, but we wanted KMS support natively in the driver without buffer
      32             :  * sharing and the ability to support an instance of VKMS per device. We first
      33             :  * looked at splitting vkms into a stub driver and a helper module that other
      34             :  * drivers could use to implement a virtual display, but this strategy ended up
      35             :  * being messy due to driver specific callbacks needed for buffer management.
      36             :  * Ultimately, it proved easier to import the vkms code as it mostly used core
      37             :  * drm helpers anyway.
      38             :  */
      39             : 
      40             : static const u32 amdgpu_vkms_formats[] = {
      41             :         DRM_FORMAT_XRGB8888,
      42             : };
      43             : 
      44           0 : static enum hrtimer_restart amdgpu_vkms_vblank_simulate(struct hrtimer *timer)
      45             : {
      46           0 :         struct amdgpu_crtc *amdgpu_crtc = container_of(timer, struct amdgpu_crtc, vblank_timer);
      47           0 :         struct drm_crtc *crtc = &amdgpu_crtc->base;
      48           0 :         struct amdgpu_vkms_output *output = drm_crtc_to_amdgpu_vkms_output(crtc);
      49             :         u64 ret_overrun;
      50             :         bool ret;
      51             : 
      52           0 :         ret_overrun = hrtimer_forward_now(&amdgpu_crtc->vblank_timer,
      53             :                                           output->period_ns);
      54           0 :         if (ret_overrun != 1)
      55           0 :                 DRM_WARN("%s: vblank timer overrun\n", __func__);
      56             : 
      57           0 :         ret = drm_crtc_handle_vblank(crtc);
      58           0 :         if (!ret)
      59           0 :                 DRM_ERROR("amdgpu_vkms failure on handling vblank");
      60             : 
      61           0 :         return HRTIMER_RESTART;
      62             : }
      63             : 
      64           0 : static int amdgpu_vkms_enable_vblank(struct drm_crtc *crtc)
      65             : {
      66           0 :         struct drm_device *dev = crtc->dev;
      67           0 :         unsigned int pipe = drm_crtc_index(crtc);
      68           0 :         struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
      69           0 :         struct amdgpu_vkms_output *out = drm_crtc_to_amdgpu_vkms_output(crtc);
      70           0 :         struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc);
      71             : 
      72           0 :         drm_calc_timestamping_constants(crtc, &crtc->mode);
      73             : 
      74           0 :         out->period_ns = ktime_set(0, vblank->framedur_ns);
      75           0 :         hrtimer_start(&amdgpu_crtc->vblank_timer, out->period_ns, HRTIMER_MODE_REL);
      76             : 
      77           0 :         return 0;
      78             : }
      79             : 
      80           0 : static void amdgpu_vkms_disable_vblank(struct drm_crtc *crtc)
      81             : {
      82           0 :         struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc);
      83             : 
      84           0 :         hrtimer_cancel(&amdgpu_crtc->vblank_timer);
      85           0 : }
      86             : 
      87           0 : static bool amdgpu_vkms_get_vblank_timestamp(struct drm_crtc *crtc,
      88             :                                              int *max_error,
      89             :                                              ktime_t *vblank_time,
      90             :                                              bool in_vblank_irq)
      91             : {
      92           0 :         struct drm_device *dev = crtc->dev;
      93           0 :         unsigned int pipe = crtc->index;
      94           0 :         struct amdgpu_vkms_output *output = drm_crtc_to_amdgpu_vkms_output(crtc);
      95           0 :         struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
      96           0 :         struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc);
      97             : 
      98           0 :         if (!READ_ONCE(vblank->enabled)) {
      99           0 :                 *vblank_time = ktime_get();
     100           0 :                 return true;
     101             :         }
     102             : 
     103           0 :         *vblank_time = READ_ONCE(amdgpu_crtc->vblank_timer.node.expires);
     104             : 
     105           0 :         if (WARN_ON(*vblank_time == vblank->time))
     106             :                 return true;
     107             : 
     108             :         /*
     109             :          * To prevent races we roll the hrtimer forward before we do any
     110             :          * interrupt processing - this is how real hw works (the interrupt is
     111             :          * only generated after all the vblank registers are updated) and what
     112             :          * the vblank core expects. Therefore we need to always correct the
     113             :          * timestampe by one frame.
     114             :          */
     115           0 :         *vblank_time -= output->period_ns;
     116             : 
     117           0 :         return true;
     118             : }
     119             : 
     120             : static const struct drm_crtc_funcs amdgpu_vkms_crtc_funcs = {
     121             :         .set_config             = drm_atomic_helper_set_config,
     122             :         .destroy                = drm_crtc_cleanup,
     123             :         .page_flip              = drm_atomic_helper_page_flip,
     124             :         .reset                  = drm_atomic_helper_crtc_reset,
     125             :         .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
     126             :         .atomic_destroy_state   = drm_atomic_helper_crtc_destroy_state,
     127             :         .enable_vblank          = amdgpu_vkms_enable_vblank,
     128             :         .disable_vblank         = amdgpu_vkms_disable_vblank,
     129             :         .get_vblank_timestamp   = amdgpu_vkms_get_vblank_timestamp,
     130             : };
     131             : 
     132           0 : static void amdgpu_vkms_crtc_atomic_enable(struct drm_crtc *crtc,
     133             :                                            struct drm_atomic_state *state)
     134             : {
     135           0 :         drm_crtc_vblank_on(crtc);
     136           0 : }
     137             : 
     138           0 : static void amdgpu_vkms_crtc_atomic_disable(struct drm_crtc *crtc,
     139             :                                             struct drm_atomic_state *state)
     140             : {
     141           0 :         drm_crtc_vblank_off(crtc);
     142           0 : }
     143             : 
     144           0 : static void amdgpu_vkms_crtc_atomic_flush(struct drm_crtc *crtc,
     145             :                                           struct drm_atomic_state *state)
     146             : {
     147             :         unsigned long flags;
     148           0 :         if (crtc->state->event) {
     149           0 :                 spin_lock_irqsave(&crtc->dev->event_lock, flags);
     150             : 
     151           0 :                 if (drm_crtc_vblank_get(crtc) != 0)
     152           0 :                         drm_crtc_send_vblank_event(crtc, crtc->state->event);
     153             :                 else
     154           0 :                         drm_crtc_arm_vblank_event(crtc, crtc->state->event);
     155             : 
     156           0 :                 spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
     157             : 
     158           0 :                 crtc->state->event = NULL;
     159             :         }
     160           0 : }
     161             : 
     162             : static const struct drm_crtc_helper_funcs amdgpu_vkms_crtc_helper_funcs = {
     163             :         .atomic_flush   = amdgpu_vkms_crtc_atomic_flush,
     164             :         .atomic_enable  = amdgpu_vkms_crtc_atomic_enable,
     165             :         .atomic_disable = amdgpu_vkms_crtc_atomic_disable,
     166             : };
     167             : 
     168           0 : static int amdgpu_vkms_crtc_init(struct drm_device *dev, struct drm_crtc *crtc,
     169             :                           struct drm_plane *primary, struct drm_plane *cursor)
     170             : {
     171           0 :         struct amdgpu_device *adev = drm_to_adev(dev);
     172           0 :         struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc);
     173             :         int ret;
     174             : 
     175           0 :         ret = drm_crtc_init_with_planes(dev, crtc, primary, cursor,
     176             :                                         &amdgpu_vkms_crtc_funcs, NULL);
     177           0 :         if (ret) {
     178           0 :                 DRM_ERROR("Failed to init CRTC\n");
     179           0 :                 return ret;
     180             :         }
     181             : 
     182           0 :         drm_crtc_helper_add(crtc, &amdgpu_vkms_crtc_helper_funcs);
     183             : 
     184           0 :         amdgpu_crtc->crtc_id = drm_crtc_index(crtc);
     185           0 :         adev->mode_info.crtcs[drm_crtc_index(crtc)] = amdgpu_crtc;
     186             : 
     187           0 :         amdgpu_crtc->pll_id = ATOM_PPLL_INVALID;
     188           0 :         amdgpu_crtc->encoder = NULL;
     189           0 :         amdgpu_crtc->connector = NULL;
     190           0 :         amdgpu_crtc->vsync_timer_enabled = AMDGPU_IRQ_STATE_DISABLE;
     191             : 
     192           0 :         hrtimer_init(&amdgpu_crtc->vblank_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
     193           0 :         amdgpu_crtc->vblank_timer.function = &amdgpu_vkms_vblank_simulate;
     194             : 
     195           0 :         return ret;
     196             : }
     197             : 
     198             : static const struct drm_connector_funcs amdgpu_vkms_connector_funcs = {
     199             :         .fill_modes = drm_helper_probe_single_connector_modes,
     200             :         .destroy = drm_connector_cleanup,
     201             :         .reset = drm_atomic_helper_connector_reset,
     202             :         .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
     203             :         .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
     204             : };
     205             : 
     206           0 : static int amdgpu_vkms_conn_get_modes(struct drm_connector *connector)
     207             : {
     208           0 :         struct drm_device *dev = connector->dev;
     209           0 :         struct drm_display_mode *mode = NULL;
     210             :         unsigned i;
     211             :         static const struct mode_size {
     212             :                 int w;
     213             :                 int h;
     214             :         } common_modes[] = {
     215             :                 { 640,  480},
     216             :                 { 720,  480},
     217             :                 { 800,  600},
     218             :                 { 848,  480},
     219             :                 {1024,  768},
     220             :                 {1152,  768},
     221             :                 {1280,  720},
     222             :                 {1280,  800},
     223             :                 {1280,  854},
     224             :                 {1280,  960},
     225             :                 {1280, 1024},
     226             :                 {1440,  900},
     227             :                 {1400, 1050},
     228             :                 {1680, 1050},
     229             :                 {1600, 1200},
     230             :                 {1920, 1080},
     231             :                 {1920, 1200},
     232             :                 {2560, 1440},
     233             :                 {4096, 3112},
     234             :                 {3656, 2664},
     235             :                 {3840, 2160},
     236             :                 {4096, 2160},
     237             :         };
     238             : 
     239           0 :         for (i = 0; i < ARRAY_SIZE(common_modes); i++) {
     240           0 :                 mode = drm_cvt_mode(dev, common_modes[i].w, common_modes[i].h, 60, false, false, false);
     241           0 :                 drm_mode_probed_add(connector, mode);
     242             :         }
     243             : 
     244           0 :         drm_set_preferred_mode(connector, XRES_DEF, YRES_DEF);
     245             : 
     246           0 :         return ARRAY_SIZE(common_modes);
     247             : }
     248             : 
     249             : static const struct drm_connector_helper_funcs amdgpu_vkms_conn_helper_funcs = {
     250             :         .get_modes    = amdgpu_vkms_conn_get_modes,
     251             : };
     252             : 
     253             : static const struct drm_plane_funcs amdgpu_vkms_plane_funcs = {
     254             :         .update_plane           = drm_atomic_helper_update_plane,
     255             :         .disable_plane          = drm_atomic_helper_disable_plane,
     256             :         .destroy                = drm_plane_cleanup,
     257             :         .reset                  = drm_atomic_helper_plane_reset,
     258             :         .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
     259             :         .atomic_destroy_state   = drm_atomic_helper_plane_destroy_state,
     260             : };
     261             : 
     262           0 : static void amdgpu_vkms_plane_atomic_update(struct drm_plane *plane,
     263             :                                             struct drm_atomic_state *old_state)
     264             : {
     265           0 :         return;
     266             : }
     267             : 
     268           0 : static int amdgpu_vkms_plane_atomic_check(struct drm_plane *plane,
     269             :                                           struct drm_atomic_state *state)
     270             : {
     271           0 :         struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state,
     272             :                                                                                  plane);
     273             :         struct drm_crtc_state *crtc_state;
     274             :         int ret;
     275             : 
     276           0 :         if (!new_plane_state->fb || WARN_ON(!new_plane_state->crtc))
     277             :                 return 0;
     278             : 
     279           0 :         crtc_state = drm_atomic_get_crtc_state(state,
     280             :                                                new_plane_state->crtc);
     281           0 :         if (IS_ERR(crtc_state))
     282           0 :                 return PTR_ERR(crtc_state);
     283             : 
     284           0 :         ret = drm_atomic_helper_check_plane_state(new_plane_state, crtc_state,
     285             :                                                   DRM_PLANE_HELPER_NO_SCALING,
     286             :                                                   DRM_PLANE_HELPER_NO_SCALING,
     287             :                                                   false, true);
     288           0 :         if (ret != 0)
     289             :                 return ret;
     290             : 
     291             :         /* for now primary plane must be visible and full screen */
     292           0 :         if (!new_plane_state->visible)
     293             :                 return -EINVAL;
     294             : 
     295           0 :         return 0;
     296             : }
     297             : 
     298           0 : static int amdgpu_vkms_prepare_fb(struct drm_plane *plane,
     299             :                                   struct drm_plane_state *new_state)
     300             : {
     301             :         struct amdgpu_framebuffer *afb;
     302             :         struct drm_gem_object *obj;
     303             :         struct amdgpu_device *adev;
     304             :         struct amdgpu_bo *rbo;
     305             :         uint32_t domain;
     306             :         int r;
     307             : 
     308           0 :         if (!new_state->fb) {
     309           0 :                 DRM_DEBUG_KMS("No FB bound\n");
     310           0 :                 return 0;
     311             :         }
     312           0 :         afb = to_amdgpu_framebuffer(new_state->fb);
     313           0 :         obj = new_state->fb->obj[0];
     314           0 :         rbo = gem_to_amdgpu_bo(obj);
     315           0 :         adev = amdgpu_ttm_adev(rbo->tbo.bdev);
     316             : 
     317           0 :         r = amdgpu_bo_reserve(rbo, true);
     318           0 :         if (r) {
     319           0 :                 dev_err(adev->dev, "fail to reserve bo (%d)\n", r);
     320           0 :                 return r;
     321             :         }
     322             : 
     323           0 :         r = dma_resv_reserve_fences(rbo->tbo.base.resv, 1);
     324           0 :         if (r) {
     325           0 :                 dev_err(adev->dev, "allocating fence slot failed (%d)\n", r);
     326           0 :                 goto error_unlock;
     327             :         }
     328             : 
     329           0 :         if (plane->type != DRM_PLANE_TYPE_CURSOR)
     330           0 :                 domain = amdgpu_display_supported_domains(adev, rbo->flags);
     331             :         else
     332             :                 domain = AMDGPU_GEM_DOMAIN_VRAM;
     333             : 
     334           0 :         r = amdgpu_bo_pin(rbo, domain);
     335           0 :         if (unlikely(r != 0)) {
     336           0 :                 if (r != -ERESTARTSYS)
     337           0 :                         DRM_ERROR("Failed to pin framebuffer with error %d\n", r);
     338             :                 goto error_unlock;
     339             :         }
     340             : 
     341           0 :         r = amdgpu_ttm_alloc_gart(&rbo->tbo);
     342           0 :         if (unlikely(r != 0)) {
     343           0 :                 DRM_ERROR("%p bind failed\n", rbo);
     344             :                 goto error_unpin;
     345             :         }
     346             : 
     347           0 :         amdgpu_bo_unreserve(rbo);
     348             : 
     349           0 :         afb->address = amdgpu_bo_gpu_offset(rbo);
     350             : 
     351           0 :         amdgpu_bo_ref(rbo);
     352             : 
     353           0 :         return 0;
     354             : 
     355             : error_unpin:
     356           0 :         amdgpu_bo_unpin(rbo);
     357             : 
     358             : error_unlock:
     359           0 :         amdgpu_bo_unreserve(rbo);
     360           0 :         return r;
     361             : }
     362             : 
     363           0 : static void amdgpu_vkms_cleanup_fb(struct drm_plane *plane,
     364             :                                    struct drm_plane_state *old_state)
     365             : {
     366             :         struct amdgpu_bo *rbo;
     367             :         int r;
     368             : 
     369           0 :         if (!old_state->fb)
     370           0 :                 return;
     371             : 
     372           0 :         rbo = gem_to_amdgpu_bo(old_state->fb->obj[0]);
     373           0 :         r = amdgpu_bo_reserve(rbo, false);
     374           0 :         if (unlikely(r)) {
     375           0 :                 DRM_ERROR("failed to reserve rbo before unpin\n");
     376           0 :                 return;
     377             :         }
     378             : 
     379           0 :         amdgpu_bo_unpin(rbo);
     380           0 :         amdgpu_bo_unreserve(rbo);
     381           0 :         amdgpu_bo_unref(&rbo);
     382             : }
     383             : 
     384             : static const struct drm_plane_helper_funcs amdgpu_vkms_primary_helper_funcs = {
     385             :         .atomic_update          = amdgpu_vkms_plane_atomic_update,
     386             :         .atomic_check           = amdgpu_vkms_plane_atomic_check,
     387             :         .prepare_fb             = amdgpu_vkms_prepare_fb,
     388             :         .cleanup_fb             = amdgpu_vkms_cleanup_fb,
     389             : };
     390             : 
     391           0 : static struct drm_plane *amdgpu_vkms_plane_init(struct drm_device *dev,
     392             :                                                 enum drm_plane_type type,
     393             :                                                 int index)
     394             : {
     395             :         struct drm_plane *plane;
     396             :         int ret;
     397             : 
     398           0 :         plane = kzalloc(sizeof(*plane), GFP_KERNEL);
     399           0 :         if (!plane)
     400             :                 return ERR_PTR(-ENOMEM);
     401             : 
     402           0 :         ret = drm_universal_plane_init(dev, plane, 1 << index,
     403             :                                        &amdgpu_vkms_plane_funcs,
     404             :                                        amdgpu_vkms_formats,
     405             :                                        ARRAY_SIZE(amdgpu_vkms_formats),
     406             :                                        NULL, type, NULL);
     407           0 :         if (ret) {
     408           0 :                 kfree(plane);
     409           0 :                 return ERR_PTR(ret);
     410             :         }
     411             : 
     412           0 :         drm_plane_helper_add(plane, &amdgpu_vkms_primary_helper_funcs);
     413             : 
     414           0 :         return plane;
     415             : }
     416             : 
     417           0 : static int amdgpu_vkms_output_init(struct drm_device *dev, struct
     418             :                                    amdgpu_vkms_output *output, int index)
     419             : {
     420           0 :         struct drm_connector *connector = &output->connector;
     421           0 :         struct drm_encoder *encoder = &output->encoder;
     422           0 :         struct drm_crtc *crtc = &output->crtc.base;
     423           0 :         struct drm_plane *primary, *cursor = NULL;
     424             :         int ret;
     425             : 
     426           0 :         primary = amdgpu_vkms_plane_init(dev, DRM_PLANE_TYPE_PRIMARY, index);
     427           0 :         if (IS_ERR(primary))
     428           0 :                 return PTR_ERR(primary);
     429             : 
     430           0 :         ret = amdgpu_vkms_crtc_init(dev, crtc, primary, cursor);
     431           0 :         if (ret)
     432             :                 goto err_crtc;
     433             : 
     434           0 :         ret = drm_connector_init(dev, connector, &amdgpu_vkms_connector_funcs,
     435             :                                  DRM_MODE_CONNECTOR_VIRTUAL);
     436           0 :         if (ret) {
     437           0 :                 DRM_ERROR("Failed to init connector\n");
     438           0 :                 goto err_connector;
     439             :         }
     440             : 
     441           0 :         drm_connector_helper_add(connector, &amdgpu_vkms_conn_helper_funcs);
     442             : 
     443           0 :         ret = drm_simple_encoder_init(dev, encoder, DRM_MODE_ENCODER_VIRTUAL);
     444           0 :         if (ret) {
     445           0 :                 DRM_ERROR("Failed to init encoder\n");
     446           0 :                 goto err_encoder;
     447             :         }
     448           0 :         encoder->possible_crtcs = 1 << index;
     449             : 
     450           0 :         ret = drm_connector_attach_encoder(connector, encoder);
     451           0 :         if (ret) {
     452           0 :                 DRM_ERROR("Failed to attach connector to encoder\n");
     453             :                 goto err_attach;
     454             :         }
     455             : 
     456           0 :         drm_mode_config_reset(dev);
     457             : 
     458           0 :         return 0;
     459             : 
     460             : err_attach:
     461           0 :         drm_encoder_cleanup(encoder);
     462             : 
     463             : err_encoder:
     464           0 :         drm_connector_cleanup(connector);
     465             : 
     466             : err_connector:
     467           0 :         drm_crtc_cleanup(crtc);
     468             : 
     469             : err_crtc:
     470           0 :         drm_plane_cleanup(primary);
     471             : 
     472           0 :         return ret;
     473             : }
     474             : 
     475             : const struct drm_mode_config_funcs amdgpu_vkms_mode_funcs = {
     476             :         .fb_create = amdgpu_display_user_framebuffer_create,
     477             :         .atomic_check = drm_atomic_helper_check,
     478             :         .atomic_commit = drm_atomic_helper_commit,
     479             : };
     480             : 
     481           0 : static int amdgpu_vkms_sw_init(void *handle)
     482             : {
     483             :         int r, i;
     484           0 :         struct amdgpu_device *adev = (struct amdgpu_device *)handle;
     485             : 
     486           0 :         adev->amdgpu_vkms_output = kcalloc(adev->mode_info.num_crtc,
     487             :                 sizeof(struct amdgpu_vkms_output), GFP_KERNEL);
     488           0 :         if (!adev->amdgpu_vkms_output)
     489             :                 return -ENOMEM;
     490             : 
     491           0 :         adev_to_drm(adev)->max_vblank_count = 0;
     492             : 
     493           0 :         adev_to_drm(adev)->mode_config.funcs = &amdgpu_vkms_mode_funcs;
     494             : 
     495           0 :         adev_to_drm(adev)->mode_config.max_width = XRES_MAX;
     496           0 :         adev_to_drm(adev)->mode_config.max_height = YRES_MAX;
     497             : 
     498           0 :         adev_to_drm(adev)->mode_config.preferred_depth = 24;
     499           0 :         adev_to_drm(adev)->mode_config.prefer_shadow = 1;
     500             : 
     501           0 :         adev_to_drm(adev)->mode_config.fb_base = adev->gmc.aper_base;
     502             : 
     503           0 :         r = amdgpu_display_modeset_create_props(adev);
     504           0 :         if (r)
     505             :                 return r;
     506             : 
     507             :         /* allocate crtcs, encoders, connectors */
     508           0 :         for (i = 0; i < adev->mode_info.num_crtc; i++) {
     509           0 :                 r = amdgpu_vkms_output_init(adev_to_drm(adev), &adev->amdgpu_vkms_output[i], i);
     510           0 :                 if (r)
     511             :                         return r;
     512             :         }
     513             : 
     514           0 :         drm_kms_helper_poll_init(adev_to_drm(adev));
     515             : 
     516           0 :         adev->mode_info.mode_config_initialized = true;
     517           0 :         return 0;
     518             : }
     519             : 
     520           0 : static int amdgpu_vkms_sw_fini(void *handle)
     521             : {
     522           0 :         struct amdgpu_device *adev = (struct amdgpu_device *)handle;
     523           0 :         int i = 0;
     524             : 
     525           0 :         for (i = 0; i < adev->mode_info.num_crtc; i++)
     526           0 :                 if (adev->mode_info.crtcs[i])
     527           0 :                         hrtimer_cancel(&adev->mode_info.crtcs[i]->vblank_timer);
     528             : 
     529           0 :         drm_kms_helper_poll_fini(adev_to_drm(adev));
     530           0 :         drm_mode_config_cleanup(adev_to_drm(adev));
     531             : 
     532           0 :         adev->mode_info.mode_config_initialized = false;
     533             : 
     534           0 :         kfree(adev->mode_info.bios_hardcoded_edid);
     535           0 :         kfree(adev->amdgpu_vkms_output);
     536           0 :         return 0;
     537             : }
     538             : 
     539           0 : static int amdgpu_vkms_hw_init(void *handle)
     540             : {
     541           0 :         struct amdgpu_device *adev = (struct amdgpu_device *)handle;
     542             : 
     543           0 :         switch (adev->asic_type) {
     544             : #ifdef CONFIG_DRM_AMDGPU_SI
     545             :         case CHIP_TAHITI:
     546             :         case CHIP_PITCAIRN:
     547             :         case CHIP_VERDE:
     548             :         case CHIP_OLAND:
     549             :                 dce_v6_0_disable_dce(adev);
     550             :                 break;
     551             : #endif
     552             : #ifdef CONFIG_DRM_AMDGPU_CIK
     553             :         case CHIP_BONAIRE:
     554             :         case CHIP_HAWAII:
     555             :         case CHIP_KAVERI:
     556             :         case CHIP_KABINI:
     557             :         case CHIP_MULLINS:
     558             :                 dce_v8_0_disable_dce(adev);
     559             :                 break;
     560             : #endif
     561             :         case CHIP_FIJI:
     562             :         case CHIP_TONGA:
     563           0 :                 dce_v10_0_disable_dce(adev);
     564           0 :                 break;
     565             :         case CHIP_CARRIZO:
     566             :         case CHIP_STONEY:
     567             :         case CHIP_POLARIS10:
     568             :         case CHIP_POLARIS11:
     569             :         case CHIP_VEGAM:
     570           0 :                 dce_v11_0_disable_dce(adev);
     571           0 :                 break;
     572             :         case CHIP_TOPAZ:
     573             : #ifdef CONFIG_DRM_AMDGPU_SI
     574             :         case CHIP_HAINAN:
     575             : #endif
     576             :                 /* no DCE */
     577             :                 break;
     578             :         default:
     579             :                 break;
     580             :         }
     581           0 :         return 0;
     582             : }
     583             : 
     584           0 : static int amdgpu_vkms_hw_fini(void *handle)
     585             : {
     586           0 :         return 0;
     587             : }
     588             : 
     589           0 : static int amdgpu_vkms_suspend(void *handle)
     590             : {
     591           0 :         struct amdgpu_device *adev = (struct amdgpu_device *)handle;
     592             :         int r;
     593             : 
     594           0 :         r = drm_mode_config_helper_suspend(adev_to_drm(adev));
     595           0 :         if (r)
     596             :                 return r;
     597           0 :         return amdgpu_vkms_hw_fini(handle);
     598             : }
     599             : 
     600           0 : static int amdgpu_vkms_resume(void *handle)
     601             : {
     602           0 :         struct amdgpu_device *adev = (struct amdgpu_device *)handle;
     603             :         int r;
     604             : 
     605           0 :         r = amdgpu_vkms_hw_init(handle);
     606           0 :         if (r)
     607             :                 return r;
     608           0 :         return drm_mode_config_helper_resume(adev_to_drm(adev));
     609             : }
     610             : 
     611           0 : static bool amdgpu_vkms_is_idle(void *handle)
     612             : {
     613           0 :         return true;
     614             : }
     615             : 
     616           0 : static int amdgpu_vkms_wait_for_idle(void *handle)
     617             : {
     618           0 :         return 0;
     619             : }
     620             : 
     621           0 : static int amdgpu_vkms_soft_reset(void *handle)
     622             : {
     623           0 :         return 0;
     624             : }
     625             : 
     626           0 : static int amdgpu_vkms_set_clockgating_state(void *handle,
     627             :                                           enum amd_clockgating_state state)
     628             : {
     629           0 :         return 0;
     630             : }
     631             : 
     632           0 : static int amdgpu_vkms_set_powergating_state(void *handle,
     633             :                                           enum amd_powergating_state state)
     634             : {
     635           0 :         return 0;
     636             : }
     637             : 
     638             : static const struct amd_ip_funcs amdgpu_vkms_ip_funcs = {
     639             :         .name = "amdgpu_vkms",
     640             :         .early_init = NULL,
     641             :         .late_init = NULL,
     642             :         .sw_init = amdgpu_vkms_sw_init,
     643             :         .sw_fini = amdgpu_vkms_sw_fini,
     644             :         .hw_init = amdgpu_vkms_hw_init,
     645             :         .hw_fini = amdgpu_vkms_hw_fini,
     646             :         .suspend = amdgpu_vkms_suspend,
     647             :         .resume = amdgpu_vkms_resume,
     648             :         .is_idle = amdgpu_vkms_is_idle,
     649             :         .wait_for_idle = amdgpu_vkms_wait_for_idle,
     650             :         .soft_reset = amdgpu_vkms_soft_reset,
     651             :         .set_clockgating_state = amdgpu_vkms_set_clockgating_state,
     652             :         .set_powergating_state = amdgpu_vkms_set_powergating_state,
     653             : };
     654             : 
     655             : const struct amdgpu_ip_block_version amdgpu_vkms_ip_block =
     656             : {
     657             :         .type = AMD_IP_BLOCK_TYPE_DCE,
     658             :         .major = 1,
     659             :         .minor = 0,
     660             :         .rev = 0,
     661             :         .funcs = &amdgpu_vkms_ip_funcs,
     662             : };
     663             : 

Generated by: LCOV version 1.14