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

Signed-off-by: Alex Deucher <alexander.deuc...@amd.com>
Cc: Lu Yao <ya...@kylinos.cn>
Cc: Jocelyn Falempe <jfale...@redhat.com>
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_display.c | 80 +++++++++++++++++++++
 drivers/gpu/drm/amd/amdgpu/amdgpu_display.h |  5 ++
 2 files changed, 85 insertions(+)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c
index b119d27271c1..35c778426a7c 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c
@@ -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;
+}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.h 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.h
index 9d19940f73c8..dfa0d642ac16 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.h
@@ -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
-- 
2.47.0

Reply via email to