drm/amdgpu: add generic display panic helper code

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

Reviewed-by: Harry Wentland <harry.wentland@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Cc: Lu Yao <yaolu@kylinos.cn>
Cc: Jocelyn Falempe <jfalempe@redhat.com>
Cc: Harry Wentland <harry.wentland@amd.com>
This commit is contained in:
Alex Deucher
2024-10-30 17:27:23 -04:00
parent e70ba46795
commit fe151ed7af
2 changed files with 85 additions and 0 deletions

View File

@@ -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;
}

View File

@@ -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