Commit fe151ed7 authored by Alex Deucher's avatar Alex Deucher
Browse files

drm/amdgpu: add generic display panic helper code



Pull this out of Jocelyn's patch and make it generic.

Reviewed-by: default avatarHarry Wentland <harry.wentland@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
Cc: Lu Yao <yaolu@kylinos.cn>
Cc: Jocelyn Falempe <jfalempe@redhat.com>
Cc: Harry Wentland <harry.wentland@amd.com>
parent e70ba467
Loading
Loading
Loading
Loading
+80 −0
Original line number Diff line number Diff line
@@ -33,6 +33,7 @@
#include "soc15_common.h"
#include "gc/gc_11_0_0_offset.h"
#include "gc/gc_11_0_0_sh_mask.h"
#include "bif/bif_4_1_d.h"
#include <asm/div64.h>

#include <linux/pci.h>
@@ -1788,3 +1789,82 @@ int amdgpu_display_resume_helper(struct amdgpu_device *adev)
	return 0;
}

/* panic_bo is set in amdgpu_dm_plane_get_scanout_buffer() and only used in amdgpu_dm_set_pixel()
 * they are called from the panic handler, and protected by the drm_panic spinlock.
 */
static struct amdgpu_bo *panic_abo;

/* Use the indirect MMIO to write each pixel to the GPU VRAM,
 * This is a simplified version of amdgpu_device_mm_access()
 */
static void amdgpu_display_set_pixel(struct drm_scanout_buffer *sb,
				     unsigned int x,
				     unsigned int y,
				     u32 color)
{
	struct amdgpu_res_cursor cursor;
	unsigned long offset;
	struct amdgpu_bo *abo = panic_abo;
	struct amdgpu_device *adev = amdgpu_ttm_adev(abo->tbo.bdev);
	uint32_t tmp;

	offset = x * 4 + y * sb->pitch[0];
	amdgpu_res_first(abo->tbo.resource, offset, 4, &cursor);

	tmp = cursor.start >> 31;
	WREG32_NO_KIQ(mmMM_INDEX, ((uint32_t) cursor.start) | 0x80000000);
	if (tmp != 0xffffffff)
		WREG32_NO_KIQ(mmMM_INDEX_HI, tmp);
	WREG32_NO_KIQ(mmMM_DATA, color);
}

int amdgpu_display_get_scanout_buffer(struct drm_plane *plane,
				      struct drm_scanout_buffer *sb)
{
	struct amdgpu_bo *abo;
	struct drm_framebuffer *fb = plane->state->fb;

	if (!fb)
		return -EINVAL;

	DRM_DEBUG_KMS("Framebuffer %dx%d %p4cc\n", fb->width, fb->height, &fb->format->format);

	abo = gem_to_amdgpu_bo(fb->obj[0]);
	if (!abo)
		return -EINVAL;

	sb->width = fb->width;
	sb->height = fb->height;
	/* Use the generic linear format, because tiling will be disabled in panic_flush() */
	sb->format = drm_format_info(fb->format->format);
	if (!sb->format)
		return -EINVAL;

	sb->pitch[0] = fb->pitches[0];

	if (abo->flags & AMDGPU_GEM_CREATE_NO_CPU_ACCESS) {
		if (abo->tbo.resource->mem_type != TTM_PL_VRAM) {
			drm_warn(plane->dev, "amdgpu panic, framebuffer not in VRAM\n");
			return -EINVAL;
		}
		/* Only handle 32bits format, to simplify mmio access */
		if (fb->format->cpp[0] != 4) {
			drm_warn(plane->dev, "amdgpu panic, pixel format is not 32bits\n");
			return -EINVAL;
		}
		sb->set_pixel = amdgpu_display_set_pixel;
		panic_abo = abo;
		return 0;
	}
	if (!abo->kmap.virtual &&
	    ttm_bo_kmap(&abo->tbo, 0, PFN_UP(abo->tbo.base.size), &abo->kmap)) {
		drm_warn(plane->dev, "amdgpu bo map failed, panic won't be displayed\n");
		return -ENOMEM;
	}
	if (abo->kmap.bo_kmap_type & TTM_BO_MAP_IOMEM_MASK)
		iosys_map_set_vaddr_iomem(&sb->map[0], abo->kmap.virtual);
	else
		iosys_map_set_vaddr(&sb->map[0], abo->kmap.virtual);

	return 0;
}
+5 −0
Original line number Diff line number Diff line
@@ -23,6 +23,8 @@
#ifndef __AMDGPU_DISPLAY_H__
#define __AMDGPU_DISPLAY_H__

#include <drm/drm_panic.h>

#define amdgpu_display_vblank_get_counter(adev, crtc) (adev)->mode_info.funcs->vblank_get_counter((adev), (crtc))
#define amdgpu_display_backlight_set_level(adev, e, l) (adev)->mode_info.funcs->backlight_set_level((e), (l))
#define amdgpu_display_backlight_get_level(adev, e) (adev)->mode_info.funcs->backlight_get_level((e))
@@ -49,4 +51,7 @@ amdgpu_lookup_format_info(u32 format, uint64_t modifier);
int amdgpu_display_suspend_helper(struct amdgpu_device *adev);
int amdgpu_display_resume_helper(struct amdgpu_device *adev);

int amdgpu_display_get_scanout_buffer(struct drm_plane *plane,
				      struct drm_scanout_buffer *sb);

#endif