Skip to content

Commit 1d26c84

Browse files
author
Jocelyn Falempe
committed
drm/nouveau: Add drm_panic support for nv50+
Add drm_panic support for nv50+ cards. It's enough to get the panic screen while running Gnome/Wayland with an nv50+ nvidia GPU. It doesn't support multi-plane or compressed format yet. Tiling is tested on GTX1650 (Turing), GeForce GT 1030 (Pascal) and Geforce 8800 GTS (Tesla). Signed-off-by: Jocelyn Falempe <[email protected]> Reviewed-by: Lyude Paul <[email protected]> Link: https://patchwork.freedesktop.org/patch/msgid/[email protected]
1 parent 74cfa1e commit 1d26c84

File tree

1 file changed

+127
-2
lines changed
  • drivers/gpu/drm/nouveau/dispnv50

1 file changed

+127
-2
lines changed

drivers/gpu/drm/nouveau/dispnv50/wndw.c

Lines changed: 127 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,14 +30,20 @@
3030
#include <nvhw/class/cl507e.h>
3131
#include <nvhw/class/clc37e.h>
3232

33+
#include <linux/iosys-map.h>
34+
3335
#include <drm/drm_atomic.h>
3436
#include <drm/drm_atomic_helper.h>
3537
#include <drm/drm_blend.h>
36-
#include <drm/drm_gem_atomic_helper.h>
3738
#include <drm/drm_fourcc.h>
39+
#include <drm/drm_framebuffer.h>
40+
#include <drm/drm_gem_atomic_helper.h>
41+
#include <drm/drm_panic.h>
42+
#include <drm/ttm/ttm_bo.h>
3843

3944
#include "nouveau_bo.h"
4045
#include "nouveau_gem.h"
46+
#include "tile.h"
4147

4248
static void
4349
nv50_wndw_ctxdma_del(struct nv50_wndw_ctxdma *ctxdma)
@@ -577,13 +583,129 @@ nv50_wndw_prepare_fb(struct drm_plane *plane, struct drm_plane_state *state)
577583
return 0;
578584
}
579585

586+
/* Only used by drm_panic get_scanout_buffer() and set_pixel(), so it is
587+
* protected by the drm panic spinlock
588+
*/
589+
static u32 nv50_panic_blk_h;
590+
591+
/* Return the framebuffer offset of the start of the block where pixel(x,y) is */
592+
static u32
593+
nv50_get_block_off(unsigned int x, unsigned int y, unsigned int pitch)
594+
{
595+
u32 blk_x, blk_y, blk_columns;
596+
597+
blk_columns = nouveau_get_width_in_blocks(pitch);
598+
blk_x = (x * 4) / NV_TILE_GOB_WIDTH_BYTES;
599+
blk_y = y / nv50_panic_blk_h;
600+
601+
return ((blk_y * blk_columns) + blk_x) * NV_TILE_GOB_WIDTH_BYTES * nv50_panic_blk_h;
602+
}
603+
604+
/* Turing and later have 2 level of tiles inside the block */
605+
static void
606+
nv50_set_pixel_swizzle(struct drm_scanout_buffer *sb, unsigned int x,
607+
unsigned int y, u32 color)
608+
{
609+
u32 blk_off, off, swizzle;
610+
611+
blk_off = nv50_get_block_off(x, y, sb->pitch[0]);
612+
613+
y = y % nv50_panic_blk_h;
614+
615+
/* Inside the block, use the fast address swizzle to compute the offset
616+
* For nvidia blocklinear, bit order is yn..y3 x3 y2 x2 y1 y0 x1 x0
617+
*/
618+
swizzle = (x & 3) | (y & 3) << 2 | (x & 4) << 2 | (y & 4) << 3;
619+
swizzle |= (x & 8) << 3 | (y >> 3) << 7;
620+
off = blk_off + swizzle * 4;
621+
622+
iosys_map_wr(&sb->map[0], off, u32, color);
623+
}
624+
625+
static void
626+
nv50_set_pixel(struct drm_scanout_buffer *sb, unsigned int x, unsigned int y,
627+
u32 color)
628+
{
629+
u32 blk_off, off;
630+
631+
blk_off = nv50_get_block_off(x, y, sb->width);
632+
633+
x = x % (NV_TILE_GOB_WIDTH_BYTES / 4);
634+
y = y % nv50_panic_blk_h;
635+
off = blk_off + x * 4 + y * NV_TILE_GOB_WIDTH_BYTES;
636+
637+
iosys_map_wr(&sb->map[0], off, u32, color);
638+
}
639+
640+
static int
641+
nv50_wndw_get_scanout_buffer(struct drm_plane *plane, struct drm_scanout_buffer *sb)
642+
{
643+
struct drm_framebuffer *fb;
644+
struct nouveau_bo *nvbo;
645+
struct nouveau_drm *drm = nouveau_drm(plane->dev);
646+
u16 chipset = drm->client.device.info.chipset;
647+
u8 family = drm->client.device.info.family;
648+
u32 tile_mode;
649+
u8 kind;
650+
651+
if (!plane->state || !plane->state->fb)
652+
return -EINVAL;
653+
654+
fb = plane->state->fb;
655+
nvbo = nouveau_gem_object(fb->obj[0]);
656+
657+
/* Don't support compressed format, or multiplane yet. */
658+
if (nvbo->comp || fb->format->num_planes != 1)
659+
return -EOPNOTSUPP;
660+
661+
if (nouveau_bo_map(nvbo)) {
662+
drm_warn(plane->dev, "nouveau bo map failed, panic won't be displayed\n");
663+
return -ENOMEM;
664+
}
665+
666+
if (nvbo->kmap.bo_kmap_type & TTM_BO_MAP_IOMEM_MASK)
667+
iosys_map_set_vaddr_iomem(&sb->map[0], (void __iomem *)nvbo->kmap.virtual);
668+
else
669+
iosys_map_set_vaddr(&sb->map[0], nvbo->kmap.virtual);
670+
671+
sb->height = fb->height;
672+
sb->width = fb->width;
673+
sb->pitch[0] = fb->pitches[0];
674+
sb->format = fb->format;
675+
676+
nouveau_framebuffer_get_layout(fb, &tile_mode, &kind);
677+
if (kind) {
678+
/* If tiling is enabled, use set_pixel() to display correctly.
679+
* Only handle 32bits format for now.
680+
*/
681+
if (fb->format->cpp[0] != 4)
682+
return -EOPNOTSUPP;
683+
nv50_panic_blk_h = nouveau_get_gob_height(family) *
684+
nouveau_get_gobs_in_block(tile_mode, chipset);
685+
686+
if (chipset >= 0x160)
687+
sb->set_pixel = nv50_set_pixel_swizzle;
688+
else
689+
sb->set_pixel = nv50_set_pixel;
690+
}
691+
return 0;
692+
}
693+
580694
static const struct drm_plane_helper_funcs
581695
nv50_wndw_helper = {
582696
.prepare_fb = nv50_wndw_prepare_fb,
583697
.cleanup_fb = nv50_wndw_cleanup_fb,
584698
.atomic_check = nv50_wndw_atomic_check,
585699
};
586700

701+
static const struct drm_plane_helper_funcs
702+
nv50_wndw_primary_helper = {
703+
.prepare_fb = nv50_wndw_prepare_fb,
704+
.cleanup_fb = nv50_wndw_cleanup_fb,
705+
.atomic_check = nv50_wndw_atomic_check,
706+
.get_scanout_buffer = nv50_wndw_get_scanout_buffer,
707+
};
708+
587709
static void
588710
nv50_wndw_atomic_destroy_state(struct drm_plane *plane,
589711
struct drm_plane_state *state)
@@ -732,7 +854,10 @@ nv50_wndw_new_(const struct nv50_wndw_func *func, struct drm_device *dev,
732854
return ret;
733855
}
734856

735-
drm_plane_helper_add(&wndw->plane, &nv50_wndw_helper);
857+
if (type == DRM_PLANE_TYPE_PRIMARY)
858+
drm_plane_helper_add(&wndw->plane, &nv50_wndw_primary_helper);
859+
else
860+
drm_plane_helper_add(&wndw->plane, &nv50_wndw_helper);
736861

737862
if (wndw->func->ilut) {
738863
ret = nv50_lut_init(disp, mmu, &wndw->ilut);

0 commit comments

Comments
 (0)