| 1 | |
| 2 |
|
| 3 | #include <drm/drm_atomic_helper.h>
|
| 4 | #include <drm/drm_edid.h>
|
| 5 | #include <drm/drm_encoder.h>
|
| 6 | #include <drm/drm_gem_framebuffer_helper.h>
|
| 7 | #include <drm/drm_vblank.h>
|
| 8 | #include <drm/drm_vblank_helper.h>
|
| 9 |
|
| 10 | #include "amdgpu.h"
|
| 11 | #ifdef CONFIG_DRM_AMDGPU_SI
|
| 12 | #include "dce_v6_0.h"
|
| 13 | #endif
|
| 14 | #ifdef CONFIG_DRM_AMDGPU_CIK
|
| 15 | #include "dce_v8_0.h"
|
| 16 | #endif
|
| 17 | #include "dce_v10_0.h"
|
| 18 | #include "ivsrcid/ivsrcid_vislands30.h"
|
| 19 | #include "amdgpu_vkms.h"
|
| 20 | #include "amdgpu_display.h"
|
| 21 | #include "atom.h"
|
| 22 | #include "amdgpu_irq.h"
|
| 23 |
|
| 24 | |
| 25 | * DOC: amdgpu_vkms
|
| 26 | *
|
| 27 | * The amdgpu vkms interface provides a virtual KMS interface for several use
|
| 28 | * cases: devices without display hardware, platforms where the actual display
|
| 29 | * hardware is not useful (e.g., servers), SR-IOV virtual functions, device
|
| 30 | * emulation/simulation, and device bring up prior to display hardware being
|
| 31 | * usable. We previously emulated a legacy KMS interface, but there was a desire
|
| 32 | * to move to the atomic KMS interface. The vkms driver did everything we
|
| 33 | * needed, but we wanted KMS support natively in the driver without buffer
|
| 34 | * sharing and the ability to support an instance of VKMS per device. We first
|
| 35 | * looked at splitting vkms into a stub driver and a helper module that other
|
| 36 | * drivers could use to implement a virtual display, but this strategy ended up
|
| 37 | * being messy due to driver specific callbacks needed for buffer management.
|
| 38 | * Ultimately, it proved easier to import the vkms code as it mostly used core
|
| 39 | * drm helpers anyway.
|
| 40 |
|
| 41 |
|
| 42 | static const u32 amdgpu_vkms_formats[] = {
|
| 43 | DRM_FORMAT_XRGB8888,
|
| 44 | };
|
| 45 |
|
| 46 | static const struct drm_crtc_funcs amdgpu_vkms_crtc_funcs = {
|
| 47 | .set_config = drm_atomic_helper_set_config,
|
| 48 | .destroy = drm_crtc_cleanup,
|
| 49 | .page_flip = drm_atomic_helper_page_flip,
|
| 50 | .reset = drm_atomic_helper_crtc_reset,
|
| 51 | .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
|
| 52 | .atomic_destroy_state = drm_atomic_helper_crtc_destroy_state,
|
| 53 | DRM_CRTC_VBLANK_TIMER_FUNCS,
|
| 54 | };
|
| 55 |
|
| 56 | static const struct drm_crtc_helper_funcs amdgpu_vkms_crtc_helper_funcs = {
|
| 57 | DRM_CRTC_HELPER_VBLANK_FUNCS,
|
| 58 | };
|
| 59 |
|
| 60 | static int amdgpu_vkms_crtc_init(struct drm_device *dev, struct drm_crtc *crtc,
|
| 61 | struct drm_plane *primary, struct drm_plane *cursor)
|
| 62 | {
|
| 63 | struct amdgpu_device *adev = drm_to_adev(dev);
|
| 64 | struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc);
|
| 65 | int ret;
|
| 66 |
|
| 67 | ret = drm_crtc_init_with_planes(dev, crtc, primary, cursor,
|
| 68 | &amdgpu_vkms_crtc_funcs, NULL);
|
| 69 | if (ret) {
|
| 70 | DRM_ERROR("Failed to init CRTC\n");
|
| 71 | return ret;
|
| 72 | }
|
| 73 |
|
| 74 | drm_crtc_helper_add(crtc, &amdgpu_vkms_crtc_helper_funcs);
|
| 75 |
|
| 76 | amdgpu_crtc->crtc_id = drm_crtc_index(crtc);
|
| 77 | adev->mode_info.crtcs[drm_crtc_index(crtc)] = amdgpu_crtc;
|
| 78 |
|
| 79 | amdgpu_crtc->pll_id = ATOM_PPLL_INVALID;
|
| 80 | amdgpu_crtc->encoder = NULL;
|
| 81 | amdgpu_crtc->connector = NULL;
|
| 82 |
|
| 83 | return ret;
|
| 84 | }
|
| 85 |
|
| 86 | static const struct drm_connector_funcs amdgpu_vkms_connector_funcs = {
|
| 87 | .fill_modes = drm_helper_probe_single_connector_modes,
|
| 88 | .destroy = drm_connector_cleanup,
|
| 89 | .reset = drm_atomic_helper_connector_reset,
|
| 90 | .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
|
| 91 | .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
|
| 92 | };
|
| 93 |
|
| 94 | static int amdgpu_vkms_conn_get_modes(struct drm_connector *connector)
|
| 95 | {
|
| 96 | struct drm_device *dev = connector->dev;
|
| 97 | struct drm_display_mode *mode = NULL;
|
| 98 | unsigned i;
|
| 99 | static const struct mode_size {
|
| 100 | int w;
|
| 101 | int h;
|
| 102 | } common_modes[] = {
|
| 103 | { 640, 480},
|
| 104 | { 720, 480},
|
| 105 | { 800, 600},
|
| 106 | { 848, 480},
|
| 107 | {1024, 768},
|
| 108 | {1152, 768},
|
| 109 | {1280, 720},
|
| 110 | {1280, 800},
|
| 111 | {1280, 854},
|
| 112 | {1280, 960},
|
| 113 | {1280, 1024},
|
| 114 | {1440, 900},
|
| 115 | {1400, 1050},
|
| 116 | {1680, 1050},
|
| 117 | {1600, 1200},
|
| 118 | {1920, 1080},
|
| 119 | {1920, 1200},
|
| 120 | {2560, 1440},
|
| 121 | {4096, 3112},
|
| 122 | {3656, 2664},
|
| 123 | {3840, 2160},
|
| 124 | {4096, 2160},
|
| 125 | };
|
| 126 |
|
| 127 | for (i = 0; i < ARRAY_SIZE(common_modes); i++) {
|
| 128 | mode = drm_cvt_mode(dev, common_modes[i].w, common_modes[i].h, 60, false, false, false);
|
| 129 | if (!mode)
|
| 130 | continue;
|
| 131 | drm_mode_probed_add(connector, mode);
|
| 132 | }
|
| 133 |
|
| 134 | drm_set_preferred_mode(connector, XRES_DEF, YRES_DEF);
|
| 135 |
|
| 136 | return ARRAY_SIZE(common_modes);
|
| 137 | }
|
| 138 |
|
| 139 | static const struct drm_connector_helper_funcs amdgpu_vkms_conn_helper_funcs = {
|
| 140 | .get_modes = amdgpu_vkms_conn_get_modes,
|
| 141 | };
|
| 142 |
|
| 143 | static const struct drm_plane_funcs amdgpu_vkms_plane_funcs = {
|
| 144 | .update_plane = drm_atomic_helper_update_plane,
|
| 145 | .disable_plane = drm_atomic_helper_disable_plane,
|
| 146 | .destroy = drm_plane_cleanup,
|
| 147 | .reset = drm_atomic_helper_plane_reset,
|
| 148 | .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
|
| 149 | .atomic_destroy_state = drm_atomic_helper_plane_destroy_state,
|
| 150 | };
|
| 151 |
|
| 152 | static void amdgpu_vkms_plane_atomic_update(struct drm_plane *plane,
|
| 153 | struct drm_atomic_commit *old_state)
|
| 154 | {
|
| 155 | return;
|
| 156 | }
|
| 157 |
|
| 158 | static int amdgpu_vkms_plane_atomic_check(struct drm_plane *plane,
|
| 159 | struct drm_atomic_commit *state)
|
| 160 | {
|
| 161 | struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state,
|
| 162 | plane);
|
| 163 | struct drm_crtc_state *crtc_state;
|
| 164 | int ret;
|
| 165 |
|
| 166 | if (!new_plane_state->fb || WARN_ON(!new_plane_state->crtc))
|
| 167 | return 0;
|
| 168 |
|
| 169 | crtc_state = drm_atomic_get_crtc_state(state,
|
| 170 | new_plane_state->crtc);
|
| 171 | if (IS_ERR(crtc_state))
|
| 172 | return PTR_ERR(crtc_state);
|
| 173 |
|
| 174 | ret = drm_atomic_helper_check_plane_state(new_plane_state, crtc_state,
|
| 175 | DRM_PLANE_NO_SCALING,
|
| 176 | DRM_PLANE_NO_SCALING,
|
| 177 | false, true);
|
| 178 | if (ret != 0)
|
| 179 | return ret;
|
| 180 |
|
| 181 |
|
| 182 | if (!new_plane_state->visible)
|
| 183 | return -EINVAL;
|
| 184 |
|
| 185 | return 0;
|
| 186 | }
|
| 187 |
|
| 188 | static int amdgpu_vkms_prepare_fb(struct drm_plane *plane,
|
| 189 | struct drm_plane_state *new_state)
|
| 190 | {
|
| 191 | struct amdgpu_framebuffer *afb;
|
| 192 | struct drm_gem_object *obj;
|
| 193 | struct amdgpu_device *adev;
|
| 194 | struct amdgpu_bo *rbo;
|
| 195 | uint32_t domain;
|
| 196 | int r;
|
| 197 |
|
| 198 | if (!new_state->fb) {
|
| 199 | DRM_DEBUG_KMS("No FB bound\n");
|
| 200 | return 0;
|
| 201 | }
|
| 202 | afb = to_amdgpu_framebuffer(new_state->fb);
|
| 203 |
|
| 204 | obj = drm_gem_fb_get_obj(new_state->fb, 0);
|
| 205 | if (!obj) {
|
| 206 | DRM_ERROR("Failed to get obj from framebuffer\n");
|
| 207 | return -EINVAL;
|
| 208 | }
|
| 209 |
|
| 210 | rbo = gem_to_amdgpu_bo(obj);
|
| 211 | adev = amdgpu_ttm_adev(rbo->tbo.bdev);
|
| 212 |
|
| 213 | r = amdgpu_bo_reserve(rbo, true);
|
| 214 | if (r) {
|
| 215 | dev_err(adev->dev, "fail to reserve bo (%d)\n", r);
|
| 216 | return r;
|
| 217 | }
|
| 218 |
|
| 219 | r = dma_resv_reserve_fences(rbo->tbo.base.resv, TTM_NUM_MOVE_FENCES);
|
| 220 | if (r)
|
| 221 | goto error_unlock;
|
| 222 |
|
| 223 | if (plane->type != DRM_PLANE_TYPE_CURSOR)
|
| 224 | domain = amdgpu_display_supported_domains(adev, rbo->flags);
|
| 225 | else
|
| 226 | domain = AMDGPU_GEM_DOMAIN_VRAM;
|
| 227 |
|
| 228 | rbo->flags |= AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS;
|
| 229 | r = amdgpu_bo_pin(rbo, domain);
|
| 230 | if (unlikely(r != 0)) {
|
| 231 | if (r != -ERESTARTSYS)
|
| 232 | DRM_ERROR("Failed to pin framebuffer with error %d\n", r);
|
| 233 | goto error_unlock;
|
| 234 | }
|
| 235 |
|
| 236 | r = amdgpu_ttm_alloc_gart(&rbo->tbo);
|
| 237 | if (unlikely(r != 0)) {
|
| 238 | DRM_ERROR("%p bind failed\n", rbo);
|
| 239 | goto error_unpin;
|
| 240 | }
|
| 241 |
|
| 242 | amdgpu_bo_unreserve(rbo);
|
| 243 |
|
| 244 | afb->address = amdgpu_bo_gpu_offset(rbo);
|
| 245 |
|
| 246 | amdgpu_bo_ref(rbo);
|
| 247 |
|
| 248 | return 0;
|
| 249 |
|
| 250 | error_unpin:
|
| 251 | amdgpu_bo_unpin(rbo);
|
| 252 |
|
| 253 | error_unlock:
|
| 254 | amdgpu_bo_unreserve(rbo);
|
| 255 | return r;
|
| 256 | }
|
| 257 |
|
| 258 | static void amdgpu_vkms_cleanup_fb(struct drm_plane *plane,
|
| 259 | struct drm_plane_state *old_state)
|
| 260 | {
|
| 261 | struct amdgpu_bo *rbo;
|
| 262 | struct drm_gem_object *obj;
|
| 263 | int r;
|
| 264 |
|
| 265 | if (!old_state->fb)
|
| 266 | return;
|
| 267 |
|
| 268 | obj = drm_gem_fb_get_obj(old_state->fb, 0);
|
| 269 | if (!obj) {
|
| 270 | DRM_ERROR("Failed to get obj from framebuffer\n");
|
| 271 | return;
|
| 272 | }
|
| 273 |
|
| 274 | rbo = gem_to_amdgpu_bo(obj);
|
| 275 | r = amdgpu_bo_reserve(rbo, false);
|
| 276 | if (unlikely(r)) {
|
| 277 | DRM_ERROR("failed to reserve rbo before unpin\n");
|
| 278 | return;
|
| 279 | }
|
| 280 |
|
| 281 | amdgpu_bo_unpin(rbo);
|
| 282 | amdgpu_bo_unreserve(rbo);
|
| 283 | amdgpu_bo_unref(&rbo);
|
| 284 | }
|
| 285 |
|
| 286 | static const struct drm_plane_helper_funcs amdgpu_vkms_primary_helper_funcs = {
|
| 287 | .atomic_update = amdgpu_vkms_plane_atomic_update,
|
| 288 | .atomic_check = amdgpu_vkms_plane_atomic_check,
|
| 289 | .prepare_fb = amdgpu_vkms_prepare_fb,
|
| 290 | .cleanup_fb = amdgpu_vkms_cleanup_fb,
|
| 291 | };
|
| 292 |
|
| 293 | static struct drm_plane *amdgpu_vkms_plane_init(struct drm_device *dev,
|
| 294 | enum drm_plane_type type,
|
| 295 | int index)
|
| 296 | {
|
| 297 | struct drm_plane *plane;
|
| 298 | int ret;
|
| 299 |
|
| 300 | plane = kzalloc_obj(*plane);
|
| 301 | if (!plane)
|
| 302 | return ERR_PTR(-ENOMEM);
|
| 303 |
|
| 304 | ret = drm_universal_plane_init(dev, plane, 1 << index,
|
| 305 | &amdgpu_vkms_plane_funcs,
|
| 306 | amdgpu_vkms_formats,
|
| 307 | ARRAY_SIZE(amdgpu_vkms_formats),
|
| 308 | NULL, type, NULL);
|
| 309 | if (ret) {
|
| 310 | kfree(plane);
|
| 311 | return ERR_PTR(ret);
|
| 312 | }
|
| 313 |
|
| 314 | drm_plane_helper_add(plane, &amdgpu_vkms_primary_helper_funcs);
|
| 315 |
|
| 316 | return plane;
|
| 317 | }
|
| 318 |
|
| 319 | static const struct drm_encoder_funcs drm_encoder_funcs_cleanup = {
|
| 320 | .destroy = drm_encoder_cleanup,
|
| 321 | };
|
| 322 |
|
| 323 | static int amdgpu_vkms_output_init(struct drm_device *dev, struct
|
| 324 | amdgpu_vkms_output *output, int index)
|
| 325 | {
|
| 326 | struct drm_connector *connector = &output->connector;
|
| 327 | struct drm_encoder *encoder = &output->encoder;
|
| 328 | struct drm_crtc *crtc = &output->crtc.base;
|
| 329 | struct drm_plane *primary, *cursor = NULL;
|
| 330 | int ret;
|
| 331 |
|
| 332 | primary = amdgpu_vkms_plane_init(dev, DRM_PLANE_TYPE_PRIMARY, index);
|
| 333 | if (IS_ERR(primary))
|
| 334 | return PTR_ERR(primary);
|
| 335 |
|
| 336 | ret = amdgpu_vkms_crtc_init(dev, crtc, primary, cursor);
|
| 337 | if (ret)
|
| 338 | goto err_crtc;
|
| 339 |
|
| 340 | ret = drm_connector_init(dev, connector, &amdgpu_vkms_connector_funcs,
|
| 341 | DRM_MODE_CONNECTOR_VIRTUAL);
|
| 342 | if (ret) {
|
| 343 | DRM_ERROR("Failed to init connector\n");
|
| 344 | goto err_connector;
|
| 345 | }
|
| 346 |
|
| 347 | drm_connector_helper_add(connector, &amdgpu_vkms_conn_helper_funcs);
|
| 348 |
|
| 349 | ret = drm_encoder_init(dev, encoder,
|
| 350 | &drm_encoder_funcs_cleanup,
|
| 351 | DRM_MODE_ENCODER_VIRTUAL, NULL);
|
| 352 | if (ret) {
|
| 353 | DRM_ERROR("Failed to init encoder\n");
|
| 354 | goto err_encoder;
|
| 355 | }
|
| 356 | encoder->possible_crtcs = 1 << index;
|
| 357 |
|
| 358 | ret = drm_connector_attach_encoder(connector, encoder);
|
| 359 | if (ret) {
|
| 360 | DRM_ERROR("Failed to attach connector to encoder\n");
|
| 361 | goto err_attach;
|
| 362 | }
|
| 363 |
|
| 364 | drm_mode_config_reset(dev);
|
| 365 |
|
| 366 | return 0;
|
| 367 |
|
| 368 | err_attach:
|
| 369 | drm_encoder_cleanup(encoder);
|
| 370 |
|
| 371 | err_encoder:
|
| 372 | drm_connector_cleanup(connector);
|
| 373 |
|
| 374 | err_connector:
|
| 375 | drm_crtc_cleanup(crtc);
|
| 376 |
|
| 377 | err_crtc:
|
| 378 | drm_plane_cleanup(primary);
|
| 379 |
|
| 380 | return ret;
|
| 381 | }
|
| 382 |
|
| 383 | const struct drm_mode_config_funcs amdgpu_vkms_mode_funcs = {
|
| 384 | .fb_create = amdgpu_display_user_framebuffer_create,
|
| 385 | .atomic_check = drm_atomic_helper_check,
|
| 386 | .atomic_commit = drm_atomic_helper_commit,
|
| 387 | };
|
| 388 |
|
| 389 | static int amdgpu_vkms_sw_init(struct amdgpu_ip_block *ip_block)
|
| 390 | {
|
| 391 | int r, i;
|
| 392 | struct amdgpu_device *adev = ip_block->adev;
|
| 393 |
|
| 394 | adev->amdgpu_vkms_output = kzalloc_objs(struct amdgpu_vkms_output,
|
| 395 | adev->mode_info.num_crtc);
|
| 396 | if (!adev->amdgpu_vkms_output)
|
| 397 | return -ENOMEM;
|
| 398 |
|
| 399 | adev_to_drm(adev)->max_vblank_count = 0;
|
| 400 |
|
| 401 | adev_to_drm(adev)->mode_config.funcs = &amdgpu_vkms_mode_funcs;
|
| 402 |
|
| 403 | adev_to_drm(adev)->mode_config.max_width = XRES_MAX;
|
| 404 | adev_to_drm(adev)->mode_config.max_height = YRES_MAX;
|
| 405 |
|
| 406 | adev_to_drm(adev)->mode_config.preferred_depth = 24;
|
| 407 | adev_to_drm(adev)->mode_config.prefer_shadow = 1;
|
| 408 |
|
| 409 | adev_to_drm(adev)->mode_config.fb_modifiers_not_supported = true;
|
| 410 |
|
| 411 | r = amdgpu_display_modeset_create_props(adev);
|
| 412 | if (r)
|
| 413 | return r;
|
| 414 |
|
| 415 |
|
| 416 | for (i = 0; i < adev->mode_info.num_crtc; i++) {
|
| 417 | r = amdgpu_vkms_output_init(adev_to_drm(adev), &adev->amdgpu_vkms_output[i], i);
|
| 418 | if (r)
|
| 419 | return r;
|
| 420 | }
|
| 421 |
|
| 422 | r = drm_vblank_init(adev_to_drm(adev), adev->mode_info.num_crtc);
|
| 423 | if (r)
|
| 424 | return r;
|
| 425 |
|
| 426 | drm_kms_helper_poll_init(adev_to_drm(adev));
|
| 427 |
|
| 428 | adev->mode_info.mode_config_initialized = true;
|
| 429 | return 0;
|
| 430 | }
|
| 431 |
|
| 432 | static int amdgpu_vkms_sw_fini(struct amdgpu_ip_block *ip_block)
|
| 433 | {
|
| 434 | struct amdgpu_device *adev = ip_block->adev;
|
| 435 |
|
| 436 | drm_kms_helper_poll_fini(adev_to_drm(adev));
|
| 437 | drm_mode_config_cleanup(adev_to_drm(adev));
|
| 438 |
|
| 439 | adev->mode_info.mode_config_initialized = false;
|
| 440 |
|
| 441 | drm_edid_free(adev->mode_info.bios_hardcoded_edid);
|
| 442 | kfree(adev->amdgpu_vkms_output);
|
| 443 | return 0;
|
| 444 | }
|
| 445 |
|
| 446 | static int amdgpu_vkms_hw_init(struct amdgpu_ip_block *ip_block)
|
| 447 | {
|
| 448 | struct amdgpu_device *adev = ip_block->adev;
|
| 449 |
|
| 450 | switch (adev->asic_type) {
|
| 451 | #ifdef CONFIG_DRM_AMDGPU_SI
|
| 452 | case CHIP_TAHITI:
|
| 453 | case CHIP_PITCAIRN:
|
| 454 | case CHIP_VERDE:
|
| 455 | case CHIP_OLAND:
|
| 456 | dce_v6_0_disable_dce(adev);
|
| 457 | break;
|
| 458 | #endif
|
| 459 | #ifdef CONFIG_DRM_AMDGPU_CIK
|
| 460 | case CHIP_BONAIRE:
|
| 461 | case CHIP_HAWAII:
|
| 462 | case CHIP_KAVERI:
|
| 463 | case CHIP_KABINI:
|
| 464 | case CHIP_MULLINS:
|
| 465 | dce_v8_0_disable_dce(adev);
|
| 466 | break;
|
| 467 | #endif
|
| 468 | case CHIP_FIJI:
|
| 469 | case CHIP_TONGA:
|
| 470 | dce_v10_0_disable_dce(adev);
|
| 471 | break;
|
| 472 | case CHIP_TOPAZ:
|
| 473 | #ifdef CONFIG_DRM_AMDGPU_SI
|
| 474 | case CHIP_HAINAN:
|
| 475 | #endif
|
| 476 |
|
| 477 | break;
|
| 478 | default:
|
| 479 | break;
|
| 480 | }
|
| 481 | return 0;
|
| 482 | }
|
| 483 |
|
| 484 | static int amdgpu_vkms_hw_fini(struct amdgpu_ip_block *ip_block)
|
| 485 | {
|
| 486 | return 0;
|
| 487 | }
|
| 488 |
|
| 489 | static int amdgpu_vkms_suspend(struct amdgpu_ip_block *ip_block)
|
| 490 | {
|
| 491 | struct amdgpu_device *adev = ip_block->adev;
|
| 492 | int r;
|
| 493 |
|
| 494 | r = drm_mode_config_helper_suspend(adev_to_drm(adev));
|
| 495 | if (r)
|
| 496 | return r;
|
| 497 |
|
| 498 | return 0;
|
| 499 | }
|
| 500 |
|
| 501 | static int amdgpu_vkms_resume(struct amdgpu_ip_block *ip_block)
|
| 502 | {
|
| 503 | int r;
|
| 504 |
|
| 505 | r = amdgpu_vkms_hw_init(ip_block);
|
| 506 | if (r)
|
| 507 | return r;
|
| 508 | return drm_mode_config_helper_resume(adev_to_drm(ip_block->adev));
|
| 509 | }
|
| 510 |
|
| 511 | static bool amdgpu_vkms_is_idle(struct amdgpu_ip_block *ip_block)
|
| 512 | {
|
| 513 | return true;
|
| 514 | }
|
| 515 |
|
| 516 | static int amdgpu_vkms_set_clockgating_state(struct amdgpu_ip_block *ip_block,
|
| 517 | enum amd_clockgating_state state)
|
| 518 | {
|
| 519 | return 0;
|
| 520 | }
|
| 521 |
|
| 522 | static int amdgpu_vkms_set_powergating_state(struct amdgpu_ip_block *ip_block,
|
| 523 | enum amd_powergating_state state)
|
| 524 | {
|
| 525 | return 0;
|
| 526 | }
|
| 527 |
|
| 528 | static const struct amd_ip_funcs amdgpu_vkms_ip_funcs = {
|
| 529 | .name = "amdgpu_vkms",
|
| 530 | .sw_init = amdgpu_vkms_sw_init,
|
| 531 | .sw_fini = amdgpu_vkms_sw_fini,
|
| 532 | .hw_init = amdgpu_vkms_hw_init,
|
| 533 | .hw_fini = amdgpu_vkms_hw_fini,
|
| 534 | .suspend = amdgpu_vkms_suspend,
|
| 535 | .resume = amdgpu_vkms_resume,
|
| 536 | .is_idle = amdgpu_vkms_is_idle,
|
| 537 | .set_clockgating_state = amdgpu_vkms_set_clockgating_state,
|
| 538 | .set_powergating_state = amdgpu_vkms_set_powergating_state,
|
| 539 | };
|
| 540 |
|
| 541 | const struct amdgpu_ip_block_version amdgpu_vkms_ip_block = {
|
| 542 | .type = AMD_IP_BLOCK_TYPE_DCE,
|
| 543 | .major = 1,
|
| 544 | .minor = 0,
|
| 545 | .rev = 0,
|
| 546 | .funcs = &amdgpu_vkms_ip_funcs,
|
| 547 | };
|
| 548 |
|