Skip to content

Commit

Permalink
Merge tag 'drm-for-v4.15-amd-dc' of git://people.freedesktop.org/~air…
Browse files Browse the repository at this point in the history
…lied/linux

Pull amdgpu DC display code for Vega from Dave Airlie:
 "This is the pull request for the AMD DC (display code) layer which is
  a requirement to program the display engines on the new Vega and Raven
  based GPUs. It also contains support for all amdgpu supported GPUs
  (CIK, VI, Polaris), which has to be enabled. It is also a kms atomic
  modesetting compatible driver (unlike the current in-tree display
  code).

  I've kept it separate from drm-next because it may have some things
  that cause you to reject it.

  Background story:

  AMD have an internal team creating a shared OS codebase for display at
  hw bring up time using information from their hardware teams. This
  process doesn't lead to the most Linux friendly/looking code but we
  have worked together on cleaning a lot of it up and dealing with
  sparse/smatch/checkpatch, and having their team internally adhere to
  Linux coding standards.

  This tree is a complete history rebased since they started opening it,
  we decided not to squash it down as the history may have some value.
  Some of the commits therefore might not reach kernel standards, and we
  are steadily training people in AMD to better write commit msgs.

  There is a major bunch of generated bandwidth calculation and
  verification code that comes from their hardware team. On Vega and
  before this is float calculations, on Raven (DCN10) this is double
  based. They do the required things to do FP in the kernel, and I could
  understand this might raise some issues. Rewriting the bandwidth would
  be a major undertaken in reverification, it's non-trivial to work out
  if a display can handle the complete set of mode information thrown at
  it.

  Future story:

  There is a TODO list with this, and it address most of the remaining
  things that would be nice to refine/remove. The DCN10 code is still
  under development internally and they push out a lot of patches quite
  regularly and are supporting this code base with their display team. I
  think we've reached the point where keeping it out of tree is going to
  motivate distributions to start carrying the code, so I'd prefer we
  get it in tree. I think this code is slightly better than STAGING
  quality but not massively so, I'd really like to see that float/double
  magic gone and fixed point used, but AMD don't seem to think the
  accuracy and revalidation of the code is worth the effort"

* tag 'drm-for-v4.15-amd-dc' of git://people.freedesktop.org/~airlied/linux: (1110 commits)
  drm/amd/display: fix MST link training fail division by 0
  drm/amd/display: Fix formatting for null pointer dereference fix
  drm/amd/display: Remove dangling planes on dc commit state
  drm/amd/display: add flip_immediate to commit update for stream
  drm/amd/display: Miss register MST encoder cbs
  drm/amd/display: Fix warnings on S3 resume
  drm/amd/display: use num_timing_generator instead of pipe_count
  drm/amd/display: use configurable FBC option in dm
  drm/amd/display: fix AZ clock not enabled before program AZ endpoint
  amdgpu/dm: Don't use DRM_ERROR in amdgpu_dm_atomic_check
  amd/display: Fix potential null dereference in dce_calcs.c
  amdgpu/dm: Remove unused forward declaration
  drm/amdgpu: Remove unused dc_stream from amdgpu_crtc
  amdgpu/dc: Fix double unlock in amdgpu_dm_commit_planes
  amdgpu/dc: Fix missing null checks in amdgpu_dm.c
  amdgpu/dc: Fix potential null dereferences in amdgpu_dm.c
  amdgpu/dc: fix more indentation warnings
  amdgpu/dc: handle allocation failures in dc_commit_planes_to_stream.
  amdgpu/dc: fix indentation warning from smatch.
  amdgpu/dc: fix non-ansi function decls.
  ...
  • Loading branch information
torvalds committed Nov 17, 2017
2 parents bec0443 + 49e37ba commit f6705bf
Show file tree
Hide file tree
Showing 368 changed files with 132,395 additions and 75 deletions.
10 changes: 10 additions & 0 deletions Documentation/gpu/todo.rst
Original file line number Diff line number Diff line change
Expand Up @@ -409,5 +409,15 @@ those drivers as simple as possible, so lots of room for refactoring:

Contact: Noralf Trønnes, Daniel Vetter

AMD DC Display Driver
---------------------

AMD DC is the display driver for AMD devices starting with Vega. There has been
a bunch of progress cleaning it up but there's still plenty of work to be done.

See drivers/gpu/drm/amd/display/TODO for tasks.

Contact: Harry Wentland, Alex Deucher

Outside DRM
===========
1 change: 1 addition & 0 deletions drivers/gpu/drm/amd/amdgpu/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -41,3 +41,4 @@ config DRM_AMDGPU_GART_DEBUGFS
pages. Uses more memory for housekeeping, enable only for debugging.

source "drivers/gpu/drm/amd/acp/Kconfig"
source "drivers/gpu/drm/amd/display/Kconfig"
17 changes: 16 additions & 1 deletion drivers/gpu/drm/amd/amdgpu/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,19 @@
# Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher.

FULL_AMD_PATH=$(src)/..
DISPLAY_FOLDER_NAME=display
FULL_AMD_DISPLAY_PATH = $(FULL_AMD_PATH)/$(DISPLAY_FOLDER_NAME)

ccflags-y := -I$(FULL_AMD_PATH)/include/asic_reg \
-I$(FULL_AMD_PATH)/include \
-I$(FULL_AMD_PATH)/amdgpu \
-I$(FULL_AMD_PATH)/scheduler \
-I$(FULL_AMD_PATH)/powerplay/inc \
-I$(FULL_AMD_PATH)/acp/include
-I$(FULL_AMD_PATH)/acp/include \
-I$(FULL_AMD_DISPLAY_PATH) \
-I$(FULL_AMD_DISPLAY_PATH)/include \
-I$(FULL_AMD_DISPLAY_PATH)/dc \
-I$(FULL_AMD_DISPLAY_PATH)/amdgpu_dm

amdgpu-y := amdgpu_drv.o

Expand Down Expand Up @@ -133,4 +139,13 @@ include $(FULL_AMD_PATH)/powerplay/Makefile

amdgpu-y += $(AMD_POWERPLAY_FILES)

ifneq ($(CONFIG_DRM_AMD_DC),)

RELATIVE_AMD_DISPLAY_PATH = ../$(DISPLAY_FOLDER_NAME)
include $(FULL_AMD_DISPLAY_PATH)/Makefile

amdgpu-y += $(AMD_DISPLAY_FILES)

endif

obj-$(CONFIG_DRM_AMDGPU)+= amdgpu.o
16 changes: 16 additions & 0 deletions drivers/gpu/drm/amd/amdgpu/amdgpu.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@
#include "amdgpu_vce.h"
#include "amdgpu_vcn.h"
#include "amdgpu_mn.h"
#include "amdgpu_dm.h"

#include "gpu_scheduler.h"
#include "amdgpu_virt.h"
Expand Down Expand Up @@ -101,6 +102,8 @@ extern int amdgpu_vm_fragment_size;
extern int amdgpu_vm_fault_stop;
extern int amdgpu_vm_debug;
extern int amdgpu_vm_update_mode;
extern int amdgpu_dc;
extern int amdgpu_dc_log;
extern int amdgpu_sched_jobs;
extern int amdgpu_sched_hw_submission;
extern int amdgpu_no_evict;
Expand Down Expand Up @@ -1535,6 +1538,7 @@ struct amdgpu_device {
/* display */
bool enable_virtual_display;
struct amdgpu_mode_info mode_info;
/* For pre-DCE11. DCE11 and later are in "struct amdgpu_device->dm" */
struct work_struct hotplug_work;
struct amdgpu_irq_src crtc_irq;
struct amdgpu_irq_src pageflip_irq;
Expand Down Expand Up @@ -1590,6 +1594,9 @@ struct amdgpu_device {
/* GDS */
struct amdgpu_gds gds;

/* display related functionality */
struct amdgpu_display_manager dm;

struct amdgpu_ip_block ip_blocks[AMDGPU_MAX_IP_NUM];
int num_ip_blocks;
struct mutex mn_lock;
Expand Down Expand Up @@ -1653,6 +1660,9 @@ void amdgpu_mm_wdoorbell(struct amdgpu_device *adev, u32 index, u32 v);
u64 amdgpu_mm_rdoorbell64(struct amdgpu_device *adev, u32 index);
void amdgpu_mm_wdoorbell64(struct amdgpu_device *adev, u32 index, u64 v);

bool amdgpu_device_asic_has_dc_support(enum amd_asic_type asic_type);
bool amdgpu_device_has_dc_support(struct amdgpu_device *adev);

/*
* Registers read & write functions.
*/
Expand Down Expand Up @@ -1911,5 +1921,11 @@ int amdgpu_cs_find_mapping(struct amdgpu_cs_parser *parser,
uint64_t addr, struct amdgpu_bo **bo,
struct amdgpu_bo_va_mapping **mapping);

#if defined(CONFIG_DRM_AMD_DC)
int amdgpu_dm_display_resume(struct amdgpu_device *adev );
#else
static inline int amdgpu_dm_display_resume(struct amdgpu_device *adev) { return 0; }
#endif

#include "amdgpu_object.h"
#endif
59 changes: 34 additions & 25 deletions drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c
Original file line number Diff line number Diff line change
Expand Up @@ -911,10 +911,6 @@ static int amdgpu_cgs_get_active_displays_info(struct cgs_device *cgs_device,
struct cgs_display_info *info)
{
CGS_FUNC_ADEV;
struct amdgpu_crtc *amdgpu_crtc;
struct drm_device *ddev = adev->ddev;
struct drm_crtc *crtc;
uint32_t line_time_us, vblank_lines;
struct cgs_mode_info *mode_info;

if (info == NULL)
Expand All @@ -928,30 +924,43 @@ static int amdgpu_cgs_get_active_displays_info(struct cgs_device *cgs_device,
mode_info->ref_clock = adev->clock.spll.reference_freq;
}

if (adev->mode_info.num_crtc && adev->mode_info.mode_config_initialized) {
list_for_each_entry(crtc,
&ddev->mode_config.crtc_list, head) {
amdgpu_crtc = to_amdgpu_crtc(crtc);
if (crtc->enabled) {
info->active_display_mask |= (1 << amdgpu_crtc->crtc_id);
info->display_count++;
}
if (mode_info != NULL &&
crtc->enabled && amdgpu_crtc->enabled &&
amdgpu_crtc->hw_mode.clock) {
line_time_us = (amdgpu_crtc->hw_mode.crtc_htotal * 1000) /
amdgpu_crtc->hw_mode.clock;
vblank_lines = amdgpu_crtc->hw_mode.crtc_vblank_end -
amdgpu_crtc->hw_mode.crtc_vdisplay +
(amdgpu_crtc->v_border * 2);
mode_info->vblank_time_us = vblank_lines * line_time_us;
mode_info->refresh_rate = drm_mode_vrefresh(&amdgpu_crtc->hw_mode);
mode_info->ref_clock = adev->clock.spll.reference_freq;
mode_info = NULL;
if (!amdgpu_device_has_dc_support(adev)) {
struct amdgpu_crtc *amdgpu_crtc;
struct drm_device *ddev = adev->ddev;
struct drm_crtc *crtc;
uint32_t line_time_us, vblank_lines;

if (adev->mode_info.num_crtc && adev->mode_info.mode_config_initialized) {
list_for_each_entry(crtc,
&ddev->mode_config.crtc_list, head) {
amdgpu_crtc = to_amdgpu_crtc(crtc);
if (crtc->enabled) {
info->active_display_mask |= (1 << amdgpu_crtc->crtc_id);
info->display_count++;
}
if (mode_info != NULL &&
crtc->enabled && amdgpu_crtc->enabled &&
amdgpu_crtc->hw_mode.clock) {
line_time_us = (amdgpu_crtc->hw_mode.crtc_htotal * 1000) /
amdgpu_crtc->hw_mode.clock;
vblank_lines = amdgpu_crtc->hw_mode.crtc_vblank_end -
amdgpu_crtc->hw_mode.crtc_vdisplay +
(amdgpu_crtc->v_border * 2);
mode_info->vblank_time_us = vblank_lines * line_time_us;
mode_info->refresh_rate = drm_mode_vrefresh(&amdgpu_crtc->hw_mode);
mode_info->ref_clock = adev->clock.spll.reference_freq;
mode_info = NULL;
}
}
}
} else {
info->display_count = adev->pm.pm_display_cfg.num_display;
if (mode_info != NULL) {
mode_info->vblank_time_us = adev->pm.pm_display_cfg.min_vblank_time;
mode_info->refresh_rate = adev->pm.pm_display_cfg.vrefresh;
mode_info->ref_clock = adev->clock.spll.reference_freq;
}
}

return 0;
}

Expand Down
105 changes: 89 additions & 16 deletions drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
#include <linux/debugfs.h>
#include <drm/drmP.h>
#include <drm/drm_crtc_helper.h>
#include <drm/drm_atomic_helper.h>
#include <drm/amdgpu_drm.h>
#include <linux/vgaarb.h>
#include <linux/vga_switcheroo.h>
Expand Down Expand Up @@ -2046,6 +2047,52 @@ static void amdgpu_device_detect_sriov_bios(struct amdgpu_device *adev)
}
}

bool amdgpu_device_asic_has_dc_support(enum amd_asic_type asic_type)
{
switch (asic_type) {
#if defined(CONFIG_DRM_AMD_DC)
case CHIP_BONAIRE:
case CHIP_HAWAII:
case CHIP_KAVERI:
case CHIP_CARRIZO:
case CHIP_STONEY:
case CHIP_POLARIS11:
case CHIP_POLARIS10:
case CHIP_POLARIS12:
case CHIP_TONGA:
case CHIP_FIJI:
#if defined(CONFIG_DRM_AMD_DC_PRE_VEGA)
return amdgpu_dc != 0;
#endif
case CHIP_KABINI:
case CHIP_MULLINS:
return amdgpu_dc > 0;
case CHIP_VEGA10:
#if defined(CONFIG_DRM_AMD_DC_DCN1_0)
case CHIP_RAVEN:
#endif
return amdgpu_dc != 0;
#endif
default:
return false;
}
}

/**
* amdgpu_device_has_dc_support - check if dc is supported
*
* @adev: amdgpu_device_pointer
*
* Returns true for supported, false for not supported
*/
bool amdgpu_device_has_dc_support(struct amdgpu_device *adev)
{
if (amdgpu_sriov_vf(adev))
return false;

return amdgpu_device_asic_has_dc_support(adev->asic_type);
}

/**
* amdgpu_device_init - initialize the driver
*
Expand Down Expand Up @@ -2100,7 +2147,6 @@ int amdgpu_device_init(struct amdgpu_device *adev,
adev->audio_endpt_rreg = &amdgpu_block_invalid_rreg;
adev->audio_endpt_wreg = &amdgpu_block_invalid_wreg;


DRM_INFO("initializing kernel modesetting (%s 0x%04X:0x%04X 0x%04X:0x%04X 0x%02X).\n",
amdgpu_asic_name[adev->asic_type], pdev->vendor, pdev->device,
pdev->subsystem_vendor, pdev->subsystem_device, pdev->revision);
Expand Down Expand Up @@ -2242,7 +2288,8 @@ int amdgpu_device_init(struct amdgpu_device *adev,
goto failed;
}
/* init i2c buses */
amdgpu_atombios_i2c_init(adev);
if (!amdgpu_device_has_dc_support(adev))
amdgpu_atombios_i2c_init(adev);
}

/* Fence driver */
Expand Down Expand Up @@ -2378,7 +2425,8 @@ void amdgpu_device_fini(struct amdgpu_device *adev)
adev->accel_working = false;
cancel_delayed_work_sync(&adev->late_init_work);
/* free i2c buses */
amdgpu_i2c_fini(adev);
if (!amdgpu_device_has_dc_support(adev))
amdgpu_i2c_fini(adev);
amdgpu_atombios_fini(adev);
kfree(adev->bios);
adev->bios = NULL;
Expand Down Expand Up @@ -2429,12 +2477,14 @@ int amdgpu_device_suspend(struct drm_device *dev, bool suspend, bool fbcon)

drm_kms_helper_poll_disable(dev);

/* turn off display hw */
drm_modeset_lock_all(dev);
list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
drm_helper_connector_dpms(connector, DRM_MODE_DPMS_OFF);
if (!amdgpu_device_has_dc_support(adev)) {
/* turn off display hw */
drm_modeset_lock_all(dev);
list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
drm_helper_connector_dpms(connector, DRM_MODE_DPMS_OFF);
}
drm_modeset_unlock_all(dev);
}
drm_modeset_unlock_all(dev);

amdgpu_amdkfd_suspend(adev);

Expand Down Expand Up @@ -2577,13 +2627,25 @@ int amdgpu_device_resume(struct drm_device *dev, bool resume, bool fbcon)

/* blat the mode back in */
if (fbcon) {
drm_helper_resume_force_mode(dev);
/* turn on display hw */
drm_modeset_lock_all(dev);
list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
drm_helper_connector_dpms(connector, DRM_MODE_DPMS_ON);
if (!amdgpu_device_has_dc_support(adev)) {
/* pre DCE11 */
drm_helper_resume_force_mode(dev);

/* turn on display hw */
drm_modeset_lock_all(dev);
list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
drm_helper_connector_dpms(connector, DRM_MODE_DPMS_ON);
}
drm_modeset_unlock_all(dev);
} else {
/*
* There is no equivalent atomic helper to turn on
* display, so we defined our own function for this,
* once suspend resume is supported by the atomic
* framework this will be reworked
*/
amdgpu_dm_display_resume(adev);
}
drm_modeset_unlock_all(dev);
}

drm_kms_helper_poll_enable(dev);
Expand All @@ -2600,7 +2662,10 @@ int amdgpu_device_resume(struct drm_device *dev, bool resume, bool fbcon)
#ifdef CONFIG_PM
dev->dev->power.disable_depth++;
#endif
drm_helper_hpd_irq_event(dev);
if (!amdgpu_device_has_dc_support(adev))
drm_helper_hpd_irq_event(dev);
else
drm_kms_helper_hotplug_event(dev);
#ifdef CONFIG_PM
dev->dev->power.disable_depth--;
#endif
Expand Down Expand Up @@ -2900,6 +2965,7 @@ int amdgpu_sriov_gpu_reset(struct amdgpu_device *adev, struct amdgpu_job *job)
*/
int amdgpu_gpu_reset(struct amdgpu_device *adev)
{
struct drm_atomic_state *state = NULL;
int i, r;
int resched;
bool need_full_reset, vram_lost = false;
Expand All @@ -2913,6 +2979,9 @@ int amdgpu_gpu_reset(struct amdgpu_device *adev)

/* block TTM */
resched = ttm_bo_lock_delayed_workqueue(&adev->mman.bdev);
/* store modesetting */
if (amdgpu_device_has_dc_support(adev))
state = drm_atomic_helper_suspend(adev->ddev);

/* block scheduler */
for (i = 0; i < AMDGPU_MAX_RINGS; ++i) {
Expand Down Expand Up @@ -3029,7 +3098,11 @@ int amdgpu_gpu_reset(struct amdgpu_device *adev)
}
}

drm_helper_resume_force_mode(adev->ddev);
if (amdgpu_device_has_dc_support(adev)) {
r = drm_atomic_helper_resume(adev->ddev, state);
amdgpu_dm_display_resume(adev);
} else
drm_helper_resume_force_mode(adev->ddev);

ttm_bo_unlock_delayed_workqueue(&adev->mman.bdev, resched);
if (r) {
Expand Down
4 changes: 2 additions & 2 deletions drivers/gpu/drm/amd/amdgpu/amdgpu_display.c
Original file line number Diff line number Diff line change
Expand Up @@ -518,7 +518,7 @@ amdgpu_framebuffer_init(struct drm_device *dev,
return 0;
}

static struct drm_framebuffer *
struct drm_framebuffer *
amdgpu_user_framebuffer_create(struct drm_device *dev,
struct drm_file *file_priv,
const struct drm_mode_fb_cmd2 *mode_cmd)
Expand Down Expand Up @@ -556,7 +556,7 @@ amdgpu_user_framebuffer_create(struct drm_device *dev,
return &amdgpu_fb->base;
}

static void amdgpu_output_poll_changed(struct drm_device *dev)
void amdgpu_output_poll_changed(struct drm_device *dev)
{
struct amdgpu_device *adev = dev->dev_private;
amdgpu_fb_output_poll_changed(adev);
Expand Down
Loading

0 comments on commit f6705bf

Please sign in to comment.