From ccd27db8c731817ef36e75de2b5fdc2e79550213 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Tue, 8 May 2018 20:39:47 +1000 Subject: [PATCH] drm/nouveau/kms/nv50-: split base implementation by hardware class Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/dispnv50/Kbuild | 2 + drivers/gpu/drm/nouveau/dispnv50/base.c | 12 +-- drivers/gpu/drm/nouveau/dispnv50/base.h | 21 ++++ drivers/gpu/drm/nouveau/dispnv50/base507c.c | 101 ++++++++------------ drivers/gpu/drm/nouveau/dispnv50/base827c.c | 67 +++++++++++++ drivers/gpu/drm/nouveau/dispnv50/base907c.c | 80 ++++++++++++++++ drivers/gpu/drm/nouveau/dispnv50/disp.c | 11 +-- drivers/gpu/drm/nouveau/dispnv50/wndw.c | 22 ++++- drivers/gpu/drm/nouveau/dispnv50/wndw.h | 5 +- 9 files changed, 242 insertions(+), 79 deletions(-) create mode 100644 drivers/gpu/drm/nouveau/dispnv50/base827c.c create mode 100644 drivers/gpu/drm/nouveau/dispnv50/base907c.c diff --git a/drivers/gpu/drm/nouveau/dispnv50/Kbuild b/drivers/gpu/drm/nouveau/dispnv50/Kbuild index cde3ae98191a..674221dea7a1 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/Kbuild +++ b/drivers/gpu/drm/nouveau/dispnv50/Kbuild @@ -24,6 +24,8 @@ nouveau-y += dispnv50/wndw.o nouveau-y += dispnv50/base.o nouveau-y += dispnv50/base507c.o +nouveau-y += dispnv50/base827c.o +nouveau-y += dispnv50/base907c.o nouveau-y += dispnv50/curs.o nouveau-y += dispnv50/curs507a.o diff --git a/drivers/gpu/drm/nouveau/dispnv50/base.c b/drivers/gpu/drm/nouveau/dispnv50/base.c index 12ca5d70509c..5f184ab833e8 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/base.c +++ b/drivers/gpu/drm/nouveau/dispnv50/base.c @@ -31,12 +31,12 @@ nv50_base_new(struct nouveau_drm *drm, int head, struct nv50_wndw **pwndw) int version; int (*new)(struct nouveau_drm *, int, s32, struct nv50_wndw **); } bases[] = { - { GK110_DISP_BASE_CHANNEL_DMA, 0, base507c_new }, - { GK104_DISP_BASE_CHANNEL_DMA, 0, base507c_new }, - { GF110_DISP_BASE_CHANNEL_DMA, 0, base507c_new }, - { GT214_DISP_BASE_CHANNEL_DMA, 0, base507c_new }, - { GT200_DISP_BASE_CHANNEL_DMA, 0, base507c_new }, - { G82_DISP_BASE_CHANNEL_DMA, 0, base507c_new }, + { GK110_DISP_BASE_CHANNEL_DMA, 0, base907c_new }, + { GK104_DISP_BASE_CHANNEL_DMA, 0, base907c_new }, + { GF110_DISP_BASE_CHANNEL_DMA, 0, base907c_new }, + { GT214_DISP_BASE_CHANNEL_DMA, 0, base827c_new }, + { GT200_DISP_BASE_CHANNEL_DMA, 0, base827c_new }, + { G82_DISP_BASE_CHANNEL_DMA, 0, base827c_new }, { NV50_DISP_BASE_CHANNEL_DMA, 0, base507c_new }, {} }; diff --git a/drivers/gpu/drm/nouveau/dispnv50/base.h b/drivers/gpu/drm/nouveau/dispnv50/base.h index 1daba7319ba9..edf96a8d645f 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/base.h +++ b/drivers/gpu/drm/nouveau/dispnv50/base.h @@ -3,6 +3,27 @@ #include "wndw.h" int base507c_new(struct nouveau_drm *, int, s32, struct nv50_wndw **); +int base507c_new_(const struct nv50_wndw_func *, const u32 *format, + struct nouveau_drm *, int head, s32 oclass, + struct nv50_wndw **); +extern const u32 base507c_format[]; +int base507c_acquire(struct nv50_wndw *, struct nv50_wndw_atom *, + struct nv50_head_atom *); +void base507c_release(struct nv50_wndw *, struct nv50_wndw_atom *, + struct nv50_head_atom *); +void base507c_sema_set(struct nv50_wndw *, struct nv50_wndw_atom *); +void base507c_sema_clr(struct nv50_wndw *); +void base507c_ntfy_reset(struct nouveau_bo *, u32); +void base507c_ntfy_set(struct nv50_wndw *, struct nv50_wndw_atom *); +void base507c_ntfy_clr(struct nv50_wndw *); +int base507c_ntfy_wait_begun(struct nouveau_bo *, u32, struct nvif_device *); +void base507c_image_clr(struct nv50_wndw *); +void base507c_lut(struct nv50_wndw *, struct nv50_wndw_atom *); +u32 base507c_update(struct nv50_wndw *, u32); + +int base827c_new(struct nouveau_drm *, int, s32, struct nv50_wndw **); + +int base907c_new(struct nouveau_drm *, int, s32, struct nv50_wndw **); int nv50_base_new(struct nouveau_drm *, int head, struct nv50_wndw **); #endif diff --git a/drivers/gpu/drm/nouveau/dispnv50/base507c.c b/drivers/gpu/drm/nouveau/dispnv50/base507c.c index b73e7b4d86a5..850c8de670b7 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/base507c.c +++ b/drivers/gpu/drm/nouveau/dispnv50/base507c.c @@ -21,7 +21,6 @@ */ #include "base.h" -#include #include #include @@ -29,23 +28,20 @@ #include #include "nouveau_bo.h" -static u32 +u32 base507c_update(struct nv50_wndw *wndw, u32 interlock) { u32 *push; - - if (!(push = evo_wait(&wndw->wndw, 2))) - return 0; - evo_mthd(push, 0x0080, 1); - evo_data(push, interlock); - evo_kick(push, &wndw->wndw); - - if (wndw->wndw.base.user.oclass < GF110_DISP_BASE_CHANNEL_DMA) + if ((push = evo_wait(&wndw->wndw, 2))) { + evo_mthd(push, 0x0080, 1); + evo_data(push, interlock); + evo_kick(push, &wndw->wndw); return interlock ? 2 << (wndw->id * 8) : 0; - return interlock ? 2 << (wndw->id * 4) : 0; + } + return 0; } -static void +void base507c_lut(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw) { u32 *push; @@ -56,7 +52,7 @@ base507c_lut(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw) } } -static void +void base507c_image_clr(struct nv50_wndw *wndw) { u32 *push; @@ -72,7 +68,6 @@ base507c_image_clr(struct nv50_wndw *wndw) static void base507c_image_set(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw) { - const s32 oclass = wndw->wndw.base.user.oclass; u32 *push; if ((push = evo_wait(&wndw->wndw, 10))) { evo_mthd(push, 0x0084, 1); @@ -80,56 +75,33 @@ base507c_image_set(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw) asyw->image.interval << 4); evo_mthd(push, 0x00c0, 1); evo_data(push, asyw->image.handle); - if (oclass < G82_DISP_BASE_CHANNEL_DMA) { - evo_mthd(push, 0x0800, 5); - evo_data(push, asyw->image.offset >> 8); - evo_data(push, 0x00000000); - evo_data(push, (asyw->image.h << 16) | asyw->image.w); - evo_data(push, (asyw->image.layout << 20) | - asyw->image.pitch | - asyw->image.block); - evo_data(push, (asyw->image.kind << 16) | - (asyw->image.format << 8)); - } else - if (oclass < GF110_DISP_BASE_CHANNEL_DMA) { - evo_mthd(push, 0x0800, 5); - evo_data(push, asyw->image.offset >> 8); - evo_data(push, 0x00000000); - evo_data(push, (asyw->image.h << 16) | asyw->image.w); - evo_data(push, (asyw->image.layout << 20) | - asyw->image.pitch | - asyw->image.block); - evo_data(push, asyw->image.format << 8); - } else { - evo_mthd(push, 0x0400, 5); - evo_data(push, asyw->image.offset >> 8); - evo_data(push, 0x00000000); - evo_data(push, (asyw->image.h << 16) | asyw->image.w); - evo_data(push, (asyw->image.layout << 24) | - asyw->image.pitch | - asyw->image.block); - evo_data(push, asyw->image.format << 8); - } + evo_mthd(push, 0x0800, 5); + evo_data(push, asyw->image.offset >> 8); + evo_data(push, 0x00000000); + evo_data(push, asyw->image.h << 16 | asyw->image.w); + evo_data(push, asyw->image.layout << 20 | + asyw->image.pitch | + asyw->image.block); + evo_data(push, asyw->image.kind << 16 | + asyw->image.format << 8); evo_kick(push, &wndw->wndw); } } -static int -base507c_ntfy_wait_begun(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw) +int +base507c_ntfy_wait_begun(struct nouveau_bo *bo, u32 offset, + struct nvif_device *device) { - struct nouveau_drm *drm = nouveau_drm(wndw->plane.dev); - struct nv50_disp *disp = nv50_disp(wndw->plane.dev); - if (nvif_msec(&drm->client.device, 2000ULL, - u32 data = nouveau_bo_rd32(disp->sync, asyw->ntfy.offset / 4); + s64 time = nvif_msec(device, 2000ULL, + u32 data = nouveau_bo_rd32(bo, offset / 4); if ((data & 0xc0000000) == 0x40000000) break; usleep_range(1, 2); - ) < 0) - return -ETIMEDOUT; - return 0; + ); + return time < 0 ? time : 0; } -static void +void base507c_ntfy_clr(struct nv50_wndw *wndw) { u32 *push; @@ -140,7 +112,7 @@ base507c_ntfy_clr(struct nv50_wndw *wndw) } } -static void +void base507c_ntfy_set(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw) { u32 *push; @@ -152,7 +124,13 @@ base507c_ntfy_set(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw) } } -static void +void +base507c_ntfy_reset(struct nouveau_bo *bo, u32 offset) +{ + nouveau_bo_wr32(bo, offset / 4, 0x00000000); +} + +void base507c_sema_clr(struct nv50_wndw *wndw) { u32 *push; @@ -163,7 +141,7 @@ base507c_sema_clr(struct nv50_wndw *wndw) } } -static void +void base507c_sema_set(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw) { u32 *push; @@ -177,14 +155,14 @@ base507c_sema_set(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw) } } -static void +void base507c_release(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw, struct nv50_head_atom *asyh) { asyh->base.cpp = 0; } -static int +int base507c_acquire(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw, struct nv50_head_atom *asyh) { @@ -229,7 +207,7 @@ base507c_acquire(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw, return 0; } -static const u32 +const u32 base507c_format[] = { DRM_FORMAT_C8, DRM_FORMAT_RGB565, @@ -250,6 +228,7 @@ base507c = { .release = base507c_release, .sema_set = base507c_sema_set, .sema_clr = base507c_sema_clr, + .ntfy_reset = base507c_ntfy_reset, .ntfy_set = base507c_ntfy_set, .ntfy_clr = base507c_ntfy_clr, .ntfy_wait_begun = base507c_ntfy_wait_begun, @@ -259,7 +238,7 @@ base507c = { .update = base507c_update, }; -static int +int base507c_new_(const struct nv50_wndw_func *func, const u32 *format, struct nouveau_drm *drm, int head, s32 oclass, struct nv50_wndw **pwndw) diff --git a/drivers/gpu/drm/nouveau/dispnv50/base827c.c b/drivers/gpu/drm/nouveau/dispnv50/base827c.c new file mode 100644 index 000000000000..0d356aeeda2b --- /dev/null +++ b/drivers/gpu/drm/nouveau/dispnv50/base827c.c @@ -0,0 +1,67 @@ +/* + * Copyright 2018 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ +#include "base.h" + +static void +base827c_image_set(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw) +{ + u32 *push; + if ((push = evo_wait(&wndw->wndw, 10))) { + evo_mthd(push, 0x0084, 1); + evo_data(push, asyw->image.mode << 8 | + asyw->image.interval << 4); + evo_mthd(push, 0x00c0, 1); + evo_data(push, asyw->image.handle); + evo_mthd(push, 0x0800, 5); + evo_data(push, asyw->image.offset >> 8); + evo_data(push, 0x00000000); + evo_data(push, asyw->image.h << 16 | asyw->image.w); + evo_data(push, asyw->image.layout << 20 | + asyw->image.pitch | + asyw->image.block); + evo_data(push, asyw->image.format << 8); + evo_kick(push, &wndw->wndw); + } +} + +static const struct nv50_wndw_func +base827c = { + .acquire = base507c_acquire, + .release = base507c_release, + .sema_set = base507c_sema_set, + .sema_clr = base507c_sema_clr, + .ntfy_reset = base507c_ntfy_reset, + .ntfy_set = base507c_ntfy_set, + .ntfy_clr = base507c_ntfy_clr, + .ntfy_wait_begun = base507c_ntfy_wait_begun, + .image_set = base827c_image_set, + .image_clr = base507c_image_clr, + .lut = base507c_lut, + .update = base507c_update, +}; + +int +base827c_new(struct nouveau_drm *drm, int head, s32 oclass, + struct nv50_wndw **pwndw) +{ + return base507c_new_(&base827c, base507c_format, drm, head, oclass, pwndw); +} diff --git a/drivers/gpu/drm/nouveau/dispnv50/base907c.c b/drivers/gpu/drm/nouveau/dispnv50/base907c.c new file mode 100644 index 000000000000..171d97872962 --- /dev/null +++ b/drivers/gpu/drm/nouveau/dispnv50/base907c.c @@ -0,0 +1,80 @@ +/* + * Copyright 2018 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ +#include "base.h" + +static u32 +base907c_update(struct nv50_wndw *wndw, u32 interlock) +{ + u32 *push; + if ((push = evo_wait(&wndw->wndw, 2))) { + evo_mthd(push, 0x0080, 1); + evo_data(push, interlock); + evo_kick(push, &wndw->wndw); + return interlock ? 2 << (wndw->id * 4) : 0; + } + return 0; +} + +static void +base907c_image_set(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw) +{ + u32 *push; + if ((push = evo_wait(&wndw->wndw, 10))) { + evo_mthd(push, 0x0084, 1); + evo_data(push, asyw->image.mode << 8 | + asyw->image.interval << 4); + evo_mthd(push, 0x00c0, 1); + evo_data(push, asyw->image.handle); + evo_mthd(push, 0x0400, 5); + evo_data(push, asyw->image.offset >> 8); + evo_data(push, 0x00000000); + evo_data(push, asyw->image.h << 16 | asyw->image.w); + evo_data(push, asyw->image.layout << 24 | + asyw->image.pitch | + asyw->image.block); + evo_data(push, asyw->image.format << 8); + evo_kick(push, &wndw->wndw); + } +} + +static const struct nv50_wndw_func +base907c = { + .acquire = base507c_acquire, + .release = base507c_release, + .sema_set = base507c_sema_set, + .sema_clr = base507c_sema_clr, + .ntfy_reset = base507c_ntfy_reset, + .ntfy_set = base507c_ntfy_set, + .ntfy_clr = base507c_ntfy_clr, + .ntfy_wait_begun = base507c_ntfy_wait_begun, + .image_set = base907c_image_set, + .image_clr = base507c_image_clr, + .lut = base507c_lut, + .update = base907c_update, +}; + +int +base907c_new(struct nouveau_drm *drm, int head, s32 oclass, + struct nv50_wndw **pwndw) +{ + return base507c_new_(&base907c, base507c_format, drm, head, oclass, pwndw); +} diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.c b/drivers/gpu/drm/nouveau/dispnv50/disp.c index 6136beeba3fc..c2b1578ed552 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/disp.c +++ b/drivers/gpu/drm/nouveau/dispnv50/disp.c @@ -1812,7 +1812,6 @@ nv50_disp_atomic_commit(struct drm_device *dev, struct drm_atomic_state *state, bool nonblock) { struct nouveau_drm *drm = nouveau_drm(dev); - struct nv50_disp *disp = nv50_disp(dev); struct drm_plane_state *new_plane_state; struct drm_plane *plane; struct drm_crtc *crtc; @@ -1847,14 +1846,8 @@ nv50_disp_atomic_commit(struct drm_device *dev, struct nv50_wndw_atom *asyw = nv50_wndw_atom(new_plane_state); struct nv50_wndw *wndw = nv50_wndw(plane); - if (asyw->set.image) { - asyw->ntfy.handle = wndw->wndw.sync.handle; - asyw->ntfy.offset = wndw->ntfy; - asyw->ntfy.awaken = false; - asyw->set.ntfy = true; - nouveau_bo_wr32(disp->sync, wndw->ntfy / 4, 0x00000000); - wndw->ntfy ^= 0x10; - } + if (asyw->set.image) + nv50_wndw_ntfy_enable(wndw, asyw); } drm_atomic_state_get(state); diff --git a/drivers/gpu/drm/nouveau/dispnv50/wndw.c b/drivers/gpu/drm/nouveau/dispnv50/wndw.c index 71a4c50af8ec..a1e53c74c8a8 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/wndw.c +++ b/drivers/gpu/drm/nouveau/dispnv50/wndw.c @@ -98,8 +98,12 @@ nv50_wndw_ctxdma_new(struct nv50_wndw *wndw, struct nouveau_framebuffer *fb) int nv50_wndw_wait_armed(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw) { - if (asyw->set.ntfy) - return wndw->func->ntfy_wait_begun(wndw, asyw); + struct nv50_disp *disp = nv50_disp(wndw->plane.dev); + if (asyw->set.ntfy) { + return wndw->func->ntfy_wait_begun(disp->sync, + asyw->ntfy.offset, + wndw->wndw.base.device); + } return 0; } @@ -138,6 +142,20 @@ nv50_wndw_flush_set(struct nv50_wndw *wndw, u32 interlock, return wndw->func->update ? wndw->func->update(wndw, interlock) : 0; } +void +nv50_wndw_ntfy_enable(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw) +{ + struct nv50_disp *disp = nv50_disp(wndw->plane.dev); + + asyw->ntfy.handle = wndw->wndw.sync.handle; + asyw->ntfy.offset = wndw->ntfy; + asyw->ntfy.awaken = false; + asyw->set.ntfy = true; + + wndw->func->ntfy_reset(disp->sync, wndw->ntfy); + wndw->ntfy ^= 0x10; +} + static void nv50_wndw_atomic_check_release(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw, diff --git a/drivers/gpu/drm/nouveau/dispnv50/wndw.h b/drivers/gpu/drm/nouveau/dispnv50/wndw.h index 1931e3068115..70259732d938 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/wndw.h +++ b/drivers/gpu/drm/nouveau/dispnv50/wndw.h @@ -41,6 +41,7 @@ u32 nv50_wndw_flush_set(struct nv50_wndw *, u32 interlock, struct nv50_wndw_atom *); u32 nv50_wndw_flush_clr(struct nv50_wndw *, u32 interlock, bool flush, struct nv50_wndw_atom *); +void nv50_wndw_ntfy_enable(struct nv50_wndw *, struct nv50_wndw_atom *); int nv50_wndw_wait_armed(struct nv50_wndw *, struct nv50_wndw_atom *); struct nv50_wndw_func { @@ -53,9 +54,11 @@ struct nv50_wndw_func { void (*sema_set)(struct nv50_wndw *, struct nv50_wndw_atom *); void (*sema_clr)(struct nv50_wndw *); + void (*ntfy_reset)(struct nouveau_bo *, u32 offset); void (*ntfy_set)(struct nv50_wndw *, struct nv50_wndw_atom *); void (*ntfy_clr)(struct nv50_wndw *); - int (*ntfy_wait_begun)(struct nv50_wndw *, struct nv50_wndw_atom *); + int (*ntfy_wait_begun)(struct nouveau_bo *, u32 offset, + struct nvif_device *); void (*image_set)(struct nv50_wndw *, struct nv50_wndw_atom *); void (*image_clr)(struct nv50_wndw *); void (*lut)(struct nv50_wndw *, struct nv50_wndw_atom *); -- 2.30.2