From 2ce7f38629891eeaf3e5d406add102a3fa6f6632 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-: initial overlay support Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/dispnv50/Kbuild | 1 + drivers/gpu/drm/nouveau/dispnv50/atom.h | 11 +++ drivers/gpu/drm/nouveau/dispnv50/base.h | 2 - drivers/gpu/drm/nouveau/dispnv50/curs.h | 1 - drivers/gpu/drm/nouveau/dispnv50/disp.h | 3 + drivers/gpu/drm/nouveau/dispnv50/head507d.c | 3 +- drivers/gpu/drm/nouveau/dispnv50/head907d.c | 2 + drivers/gpu/drm/nouveau/dispnv50/oimm507b.c | 6 +- drivers/gpu/drm/nouveau/dispnv50/ovly.c | 2 +- drivers/gpu/drm/nouveau/dispnv50/ovly.h | 14 +++ drivers/gpu/drm/nouveau/dispnv50/ovly507e.c | 144 ++++++++++++++++++++++++++++ drivers/gpu/drm/nouveau/dispnv50/ovly827e.c | 66 ++++++++++++- drivers/gpu/drm/nouveau/dispnv50/ovly907e.c | 38 +++++++- drivers/gpu/drm/nouveau/dispnv50/ovly917e.c | 45 +++++++++ drivers/gpu/drm/nouveau/dispnv50/wndw.c | 35 ++++++- drivers/gpu/drm/nouveau/dispnv50/wndw.h | 6 ++ 16 files changed, 364 insertions(+), 15 deletions(-) create mode 100644 drivers/gpu/drm/nouveau/dispnv50/ovly917e.c diff --git a/drivers/gpu/drm/nouveau/dispnv50/Kbuild b/drivers/gpu/drm/nouveau/dispnv50/Kbuild index 7c337fd80158..ebd18cb9feda 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/Kbuild +++ b/drivers/gpu/drm/nouveau/dispnv50/Kbuild @@ -40,3 +40,4 @@ nouveau-y += dispnv50/ovly.o nouveau-y += dispnv50/ovly507e.o nouveau-y += dispnv50/ovly827e.o nouveau-y += dispnv50/ovly907e.o +nouveau-y += dispnv50/ovly917e.o diff --git a/drivers/gpu/drm/nouveau/dispnv50/atom.h b/drivers/gpu/drm/nouveau/dispnv50/atom.h index 3d059df78322..d8337e7996e8 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/atom.h +++ b/drivers/gpu/drm/nouveau/dispnv50/atom.h @@ -173,6 +173,7 @@ struct nv50_wndw_atom { u8 mode:2; u8 interval:4; + u8 colorspace:2; u8 format; u8 kind:7; u8 layout:1; @@ -187,6 +188,15 @@ struct nv50_wndw_atom { } image; struct { + u16 sx; + u16 sy; + u16 sw; + u16 sh; + u16 dw; + u16 dh; + } scale; + + struct { u16 x; u16 y; } point; @@ -197,6 +207,7 @@ struct nv50_wndw_atom { bool sema:1; bool xlut:1; bool image:1; + bool scale:1; bool point:1; }; u8 mask; diff --git a/drivers/gpu/drm/nouveau/dispnv50/base.h b/drivers/gpu/drm/nouveau/dispnv50/base.h index 7afd9e26f9f9..e7f14f230f35 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/base.h +++ b/drivers/gpu/drm/nouveau/dispnv50/base.h @@ -13,10 +13,8 @@ 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_xlut_set(struct nv50_wndw *, struct nv50_wndw_atom *); void base507c_xlut_clr(struct nv50_wndw *); void base507c_image_clr(struct nv50_wndw *); diff --git a/drivers/gpu/drm/nouveau/dispnv50/curs.h b/drivers/gpu/drm/nouveau/dispnv50/curs.h index 2285247dc2a3..8edac4507ec8 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/curs.h +++ b/drivers/gpu/drm/nouveau/dispnv50/curs.h @@ -6,7 +6,6 @@ int curs507a_new(struct nouveau_drm *, int, s32, struct nv50_wndw **); int curs507a_new_(const struct nv50_wimm_func *, struct nouveau_drm *, int head, s32 oclass, u32 interlock_data, struct nv50_wndw **); -extern const struct nv50_wimm_func curs507a; int curs907a_new(struct nouveau_drm *, int, s32, struct nv50_wndw **); diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.h b/drivers/gpu/drm/nouveau/dispnv50/disp.h index f3a963b0ab77..a89b83f95187 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/disp.h +++ b/drivers/gpu/drm/nouveau/dispnv50/disp.h @@ -16,6 +16,9 @@ struct nv50_disp { #define NV50_DISP_BASE_SEM0(c) NV50_DISP_WNDW_SEM0(0 + (c)) #define NV50_DISP_BASE_SEM1(c) NV50_DISP_WNDW_SEM1(0 + (c)) #define NV50_DISP_BASE_NTFY(c) NV50_DISP_WNDW_NTFY(0 + (c)) +#define NV50_DISP_OVLY_SEM0(c) NV50_DISP_WNDW_SEM0(4 + (c)) +#define NV50_DISP_OVLY_SEM1(c) NV50_DISP_WNDW_SEM1(4 + (c)) +#define NV50_DISP_OVLY_NTFY(c) NV50_DISP_WNDW_NTFY(4 + (c)) struct nouveau_bo *sync; struct mutex mutex; diff --git a/drivers/gpu/drm/nouveau/dispnv50/head507d.c b/drivers/gpu/drm/nouveau/dispnv50/head507d.c index 5b6a280ab804..51bc5996fd37 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/head507d.c +++ b/drivers/gpu/drm/nouveau/dispnv50/head507d.c @@ -58,7 +58,6 @@ head507d_ovly(struct nv50_head *head, struct nv50_head_atom *asyh) if (asyh->ovly.cpp) { switch (asyh->ovly.cpp) { - case 8: bounds |= 0x00000500; break; case 4: bounds |= 0x00000300; break; case 2: bounds |= 0x00000100; break; default: @@ -66,6 +65,8 @@ head507d_ovly(struct nv50_head *head, struct nv50_head_atom *asyh) break; } bounds |= 0x00000001; + } else { + bounds |= 0x00000100; } if ((push = evo_wait(core, 2))) { diff --git a/drivers/gpu/drm/nouveau/dispnv50/head907d.c b/drivers/gpu/drm/nouveau/dispnv50/head907d.c index c09620f540f9..633907163eb1 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/head907d.c +++ b/drivers/gpu/drm/nouveau/dispnv50/head907d.c @@ -82,6 +82,8 @@ head907d_ovly(struct nv50_head *head, struct nv50_head_atom *asyh) break; } bounds |= 0x00000001; + } else { + bounds |= 0x00000100; } if ((push = evo_wait(core, 2))) { diff --git a/drivers/gpu/drm/nouveau/dispnv50/oimm507b.c b/drivers/gpu/drm/nouveau/dispnv50/oimm507b.c index c4baca82de14..2ee404b3e19f 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/oimm507b.c +++ b/drivers/gpu/drm/nouveau/dispnv50/oimm507b.c @@ -23,10 +23,6 @@ #include -static const struct nv50_wimm_func -oimm507b = { -}; - static int oimm507b_init_(const struct nv50_wimm_func *func, struct nouveau_drm *drm, s32 oclass, struct nv50_wndw *wndw) @@ -52,5 +48,5 @@ oimm507b_init_(const struct nv50_wimm_func *func, struct nouveau_drm *drm, int oimm507b_init(struct nouveau_drm *drm, s32 oclass, struct nv50_wndw *wndw) { - return oimm507b_init_(&oimm507b, drm, oclass, wndw); + return oimm507b_init_(&curs507a, drm, oclass, wndw); } diff --git a/drivers/gpu/drm/nouveau/dispnv50/ovly.c b/drivers/gpu/drm/nouveau/dispnv50/ovly.c index be0f16fdcd5b..90c246d47604 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/ovly.c +++ b/drivers/gpu/drm/nouveau/dispnv50/ovly.c @@ -32,7 +32,7 @@ nv50_ovly_new(struct nouveau_drm *drm, int head, struct nv50_wndw **pwndw) int version; int (*new)(struct nouveau_drm *, int, s32, struct nv50_wndw **); } ovlys[] = { - { GK104_DISP_OVERLAY_CONTROL_DMA, 0, ovly907e_new }, + { GK104_DISP_OVERLAY_CONTROL_DMA, 0, ovly917e_new }, { GF110_DISP_OVERLAY_CONTROL_DMA, 0, ovly907e_new }, { GT214_DISP_OVERLAY_CHANNEL_DMA, 0, ovly827e_new }, { GT200_DISP_OVERLAY_CHANNEL_DMA, 0, ovly827e_new }, diff --git a/drivers/gpu/drm/nouveau/dispnv50/ovly.h b/drivers/gpu/drm/nouveau/dispnv50/ovly.h index d149ef6f957e..4869d52d1786 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/ovly.h +++ b/drivers/gpu/drm/nouveau/dispnv50/ovly.h @@ -6,11 +6,25 @@ int ovly507e_new(struct nouveau_drm *, int, s32, struct nv50_wndw **); int ovly507e_new_(const struct nv50_wndw_func *, const u32 *format, struct nouveau_drm *, int head, s32 oclass, u32 interlock_data, struct nv50_wndw **); +int ovly507e_acquire(struct nv50_wndw *, struct nv50_wndw_atom *, + struct nv50_head_atom *); +void ovly507e_release(struct nv50_wndw *, struct nv50_wndw_atom *, + struct nv50_head_atom *); +void ovly507e_ntfy_set(struct nv50_wndw *, struct nv50_wndw_atom *); +void ovly507e_ntfy_clr(struct nv50_wndw *); +void ovly507e_image_clr(struct nv50_wndw *); +void ovly507e_scale_set(struct nv50_wndw *, struct nv50_wndw_atom *); +void ovly507e_update(struct nv50_wndw *, u32 *); extern const u32 ovly827e_format[]; +void ovly827e_ntfy_reset(struct nouveau_bo *, u32); +int ovly827e_ntfy_wait_begun(struct nouveau_bo *, u32, struct nvif_device *); + +extern const struct nv50_wndw_func ovly907e; int ovly827e_new(struct nouveau_drm *, int, s32, struct nv50_wndw **); int ovly907e_new(struct nouveau_drm *, int, s32, struct nv50_wndw **); +int ovly917e_new(struct nouveau_drm *, int, s32, struct nv50_wndw **); int nv50_ovly_new(struct nouveau_drm *, int head, struct nv50_wndw **); #endif diff --git a/drivers/gpu/drm/nouveau/dispnv50/ovly507e.c b/drivers/gpu/drm/nouveau/dispnv50/ovly507e.c index 732eea39e4de..cc417664f823 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/ovly507e.c +++ b/drivers/gpu/drm/nouveau/dispnv50/ovly507e.c @@ -20,17 +20,149 @@ * OTHER DEALINGS IN THE SOFTWARE. */ #include "ovly.h" +#include "atom.h" + +#include +#include #include +#include + +void +ovly507e_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[NV50_DISP_INTERLOCK_CORE]); + evo_kick(push, &wndw->wndw); + } +} + +void +ovly507e_scale_set(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw) +{ + u32 *push; + if ((push = evo_wait(&wndw->wndw, 4))) { + evo_mthd(push, 0x00e0, 3); + evo_data(push, asyw->scale.sy << 16 | asyw->scale.sx); + evo_data(push, asyw->scale.sh << 16 | asyw->scale.sw); + evo_data(push, asyw->scale.dw); + evo_kick(push, &wndw->wndw); + } +} + +void +ovly507e_image_clr(struct nv50_wndw *wndw) +{ + u32 *push; + if ((push = evo_wait(&wndw->wndw, 4))) { + evo_mthd(push, 0x0084, 1); + evo_data(push, 0x00000000); + evo_mthd(push, 0x00c0, 1); + evo_data(push, 0x00000000); + evo_kick(push, &wndw->wndw); + } +} + +static void +ovly507e_image_set(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw) +{ + u32 *push; + if ((push = evo_wait(&wndw->wndw, 12))) { + evo_mthd(push, 0x0084, 1); + evo_data(push, asyw->image.interval << 4); + evo_mthd(push, 0x00c0, 1); + evo_data(push, asyw->image.handle[0]); + evo_mthd(push, 0x0100, 1); + evo_data(push, 0x00000002); + evo_mthd(push, 0x0800, 1); + evo_data(push, asyw->image.offset[0] >> 8); + evo_mthd(push, 0x0808, 3); + evo_data(push, asyw->image.h << 16 | asyw->image.w); + evo_data(push, asyw->image.layout << 20 | + (asyw->image.pitch[0] >> 8) << 8 | + asyw->image.blocks[0] << 8 | + asyw->image.blockh); + evo_data(push, asyw->image.kind << 16 | + asyw->image.format << 8 | + asyw->image.colorspace); + evo_kick(push, &wndw->wndw); + } +} + +void +ovly507e_ntfy_clr(struct nv50_wndw *wndw) +{ + u32 *push; + if ((push = evo_wait(&wndw->wndw, 2))) { + evo_mthd(push, 0x00a4, 1); + evo_data(push, 0x00000000); + evo_kick(push, &wndw->wndw); + } +} + +void +ovly507e_ntfy_set(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw) +{ + u32 *push; + if ((push = evo_wait(&wndw->wndw, 3))) { + evo_mthd(push, 0x00a0, 2); + evo_data(push, asyw->ntfy.awaken << 30 | asyw->ntfy.offset); + evo_data(push, asyw->ntfy.handle); + evo_kick(push, &wndw->wndw); + } +} + +void +ovly507e_release(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw, + struct nv50_head_atom *asyh) +{ + asyh->ovly.cpp = 0; +} + +int +ovly507e_acquire(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw, + struct nv50_head_atom *asyh) +{ + const struct drm_framebuffer *fb = asyw->state.fb; + int ret; + + ret = drm_atomic_helper_check_plane_state(&asyw->state, &asyh->state, + DRM_PLANE_HELPER_NO_SCALING, + DRM_PLANE_HELPER_NO_SCALING, + true, true); + if (ret) + return ret; + + asyh->ovly.cpp = fb->format->cpp[0]; + return 0; +} #include "nouveau_bo.h" static const struct nv50_wndw_func ovly507e = { + .acquire = ovly507e_acquire, + .release = ovly507e_release, + .ntfy_set = ovly507e_ntfy_set, + .ntfy_clr = ovly507e_ntfy_clr, + .ntfy_reset = base507c_ntfy_reset, + .ntfy_wait_begun = base507c_ntfy_wait_begun, + .image_set = ovly507e_image_set, + .image_clr = ovly507e_image_clr, + .scale_set = ovly507e_scale_set, + .update = ovly507e_update, }; static const u32 ovly507e_format[] = { + DRM_FORMAT_YUYV, + DRM_FORMAT_UYVY, + DRM_FORMAT_XRGB8888, + DRM_FORMAT_ARGB8888, + DRM_FORMAT_XRGB1555, + DRM_FORMAT_ARGB1555, 0 }; @@ -61,6 +193,18 @@ ovly507e_new_(const struct nv50_wndw_func *func, const u32 *format, return ret; } + ret = nvif_notify_init(&wndw->wndw.base.user, wndw->notify.func, false, + NV50_DISP_OVERLAY_CHANNEL_DMA_V0_NTFY_UEVENT, + &(struct nvif_notify_uevent_req) {}, + sizeof(struct nvif_notify_uevent_req), + sizeof(struct nvif_notify_uevent_rep), + &wndw->notify); + if (ret) + return ret; + + wndw->ntfy = NV50_DISP_OVLY_NTFY(wndw->id); + wndw->sema = NV50_DISP_OVLY_SEM0(wndw->id); + wndw->data = 0x00000000; return 0; } diff --git a/drivers/gpu/drm/nouveau/dispnv50/ovly827e.c b/drivers/gpu/drm/nouveau/dispnv50/ovly827e.c index a8115f13406e..aaa9fe5a4fc8 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/ovly827e.c +++ b/drivers/gpu/drm/nouveau/dispnv50/ovly827e.c @@ -20,17 +20,81 @@ * OTHER DEALINGS IN THE SOFTWARE. */ #include "ovly.h" +#include "atom.h" #include -#include +static void +ovly827e_image_set(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw) +{ + u32 *push; + if ((push = evo_wait(&wndw->wndw, 12))) { + evo_mthd(push, 0x0084, 1); + evo_data(push, asyw->image.interval << 4); + evo_mthd(push, 0x00c0, 1); + evo_data(push, asyw->image.handle[0]); + evo_mthd(push, 0x0100, 1); + evo_data(push, 0x00000002); + evo_mthd(push, 0x0800, 1); + evo_data(push, asyw->image.offset[0] >> 8); + evo_mthd(push, 0x0808, 3); + evo_data(push, asyw->image.h << 16 | asyw->image.w); + evo_data(push, asyw->image.layout << 20 | + (asyw->image.pitch[0] >> 8) << 8 | + asyw->image.blocks[0] << 8 | + asyw->image.blockh); + evo_data(push, asyw->image.format << 8 | + asyw->image.colorspace); + evo_kick(push, &wndw->wndw); + } +} + +int +ovly827e_ntfy_wait_begun(struct nouveau_bo *bo, u32 offset, + struct nvif_device *device) +{ + s64 time = nvif_msec(device, 2000ULL, + u32 data = nouveau_bo_rd32(bo, offset / 4 + 3); + if ((data & 0xffff0000) == 0xffff0000) + break; + usleep_range(1, 2); + ); + return time < 0 ? time : 0; +} + +void +ovly827e_ntfy_reset(struct nouveau_bo *bo, u32 offset) +{ + nouveau_bo_wr32(bo, offset / 4 + 0, 0x00000000); + nouveau_bo_wr32(bo, offset / 4 + 1, 0x00000000); + nouveau_bo_wr32(bo, offset / 4 + 2, 0x00000000); + nouveau_bo_wr32(bo, offset / 4 + 3, 0x80000000); +} static const struct nv50_wndw_func ovly827e = { + .acquire = ovly507e_acquire, + .release = ovly507e_release, + .ntfy_set = ovly507e_ntfy_set, + .ntfy_clr = ovly507e_ntfy_clr, + .ntfy_reset = ovly827e_ntfy_reset, + .ntfy_wait_begun = ovly827e_ntfy_wait_begun, + .image_set = ovly827e_image_set, + .image_clr = ovly507e_image_clr, + .scale_set = ovly507e_scale_set, + .update = ovly507e_update, }; const u32 ovly827e_format[] = { + DRM_FORMAT_YUYV, + DRM_FORMAT_UYVY, + DRM_FORMAT_XRGB8888, + DRM_FORMAT_ARGB8888, + DRM_FORMAT_XRGB1555, + DRM_FORMAT_ARGB1555, + DRM_FORMAT_XBGR2101010, + DRM_FORMAT_ABGR2101010, 0 }; diff --git a/drivers/gpu/drm/nouveau/dispnv50/ovly907e.c b/drivers/gpu/drm/nouveau/dispnv50/ovly907e.c index f50da6461d41..a3ce53046015 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/ovly907e.c +++ b/drivers/gpu/drm/nouveau/dispnv50/ovly907e.c @@ -20,9 +20,45 @@ * OTHER DEALINGS IN THE SOFTWARE. */ #include "ovly.h" +#include "atom.h" -static const struct nv50_wndw_func +static void +ovly907e_image_set(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw) +{ + u32 *push; + if ((push = evo_wait(&wndw->wndw, 12))) { + evo_mthd(push, 0x0084, 1); + evo_data(push, asyw->image.interval << 4); + evo_mthd(push, 0x00c0, 1); + evo_data(push, asyw->image.handle[0]); + evo_mthd(push, 0x0100, 1); + evo_data(push, 0x00000002); + evo_mthd(push, 0x0400, 1); + evo_data(push, asyw->image.offset[0] >> 8); + evo_mthd(push, 0x0408, 3); + evo_data(push, asyw->image.h << 16 | asyw->image.w); + evo_data(push, asyw->image.layout << 24 | + (asyw->image.pitch[0] >> 8) << 8 | + asyw->image.blocks[0] << 8 | + asyw->image.blockh); + evo_data(push, asyw->image.format << 8 | + asyw->image.colorspace); + evo_kick(push, &wndw->wndw); + } +} + +const struct nv50_wndw_func ovly907e = { + .acquire = ovly507e_acquire, + .release = ovly507e_release, + .ntfy_set = ovly507e_ntfy_set, + .ntfy_clr = ovly507e_ntfy_clr, + .ntfy_reset = ovly827e_ntfy_reset, + .ntfy_wait_begun = ovly827e_ntfy_wait_begun, + .image_set = ovly907e_image_set, + .image_clr = ovly507e_image_clr, + .scale_set = ovly507e_scale_set, + .update = ovly507e_update, }; int diff --git a/drivers/gpu/drm/nouveau/dispnv50/ovly917e.c b/drivers/gpu/drm/nouveau/dispnv50/ovly917e.c new file mode 100644 index 000000000000..505fa7e78523 --- /dev/null +++ b/drivers/gpu/drm/nouveau/dispnv50/ovly917e.c @@ -0,0 +1,45 @@ +/* + * 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 "ovly.h" + +static const u32 +ovly917e_format[] = { + DRM_FORMAT_YUYV, + DRM_FORMAT_UYVY, + DRM_FORMAT_XRGB8888, + DRM_FORMAT_ARGB8888, + DRM_FORMAT_XRGB1555, + DRM_FORMAT_ARGB1555, + DRM_FORMAT_XBGR2101010, + DRM_FORMAT_ABGR2101010, + DRM_FORMAT_XRGB2101010, + DRM_FORMAT_ARGB2101010, + 0 +}; + +int +ovly917e_new(struct nouveau_drm *drm, int head, s32 oclass, + struct nv50_wndw **pwndw) +{ + return ovly507e_new_(&ovly907e, ovly917e_format, drm, head, oclass, + 0x00000004 << (head * 4), pwndw); +} diff --git a/drivers/gpu/drm/nouveau/dispnv50/wndw.c b/drivers/gpu/drm/nouveau/dispnv50/wndw.c index 861fb0ec6b61..c7c08fae383f 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/wndw.c +++ b/drivers/gpu/drm/nouveau/dispnv50/wndw.c @@ -146,6 +146,7 @@ nv50_wndw_flush_set(struct nv50_wndw *wndw, u32 *interlock, wndw->func->xlut_set(wndw, asyw); } + if (asyw->set.scale) wndw->func->scale_set(wndw, asyw); if (asyw->set.point) { wndw->immd->point(wndw, asyw); wndw->immd->update(wndw, interlock); @@ -181,6 +182,20 @@ nv50_wndw_atomic_check_release(struct nv50_wndw *wndw, } static int +nv50_wndw_atomic_check_acquire_yuv(struct nv50_wndw_atom *asyw) +{ + switch (asyw->state.fb->format->format) { + case DRM_FORMAT_YUYV: asyw->image.format = 0x28; break; + case DRM_FORMAT_UYVY: asyw->image.format = 0x29; break; + default: + WARN_ON(1); + return -EINVAL; + } + asyw->image.colorspace = 1; + return 0; +} + +static int nv50_wndw_atomic_check_acquire_rgb(struct nv50_wndw_atom *asyw) { switch (asyw->state.fb->format->format) { @@ -197,9 +212,9 @@ nv50_wndw_atomic_check_acquire_rgb(struct nv50_wndw_atom *asyw) case DRM_FORMAT_XRGB2101010: case DRM_FORMAT_ARGB2101010: asyw->image.format = 0xdf; break; default: - WARN_ON(1); return -EINVAL; } + asyw->image.colorspace = 0; return 0; } @@ -221,8 +236,11 @@ nv50_wndw_atomic_check_acquire(struct nv50_wndw *wndw, bool modeset, asyw->image.kind = fb->nvbo->kind; ret = nv50_wndw_atomic_check_acquire_rgb(asyw); - if (ret) - return ret; + if (ret) { + ret = nv50_wndw_atomic_check_acquire_yuv(asyw); + if (ret) + return ret; + } if (asyw->image.kind) { asyw->image.layout = 0; @@ -247,6 +265,17 @@ nv50_wndw_atomic_check_acquire(struct nv50_wndw *wndw, bool modeset, asyw->set.image = wndw->func->image_set != NULL; } + if (wndw->func->scale_set) { + asyw->scale.sx = asyw->state.src_x >> 16; + asyw->scale.sy = asyw->state.src_y >> 16; + asyw->scale.sw = asyw->state.src_w >> 16; + asyw->scale.sh = asyw->state.src_h >> 16; + asyw->scale.dw = asyw->state.crtc_w; + asyw->scale.dh = asyw->state.crtc_h; + if (memcmp(&armw->scale, &asyw->scale, sizeof(asyw->scale))) + asyw->set.scale = true; + } + if (wndw->immd) { asyw->point.x = asyw->state.crtc_x; asyw->point.y = asyw->state.crtc_y; diff --git a/drivers/gpu/drm/nouveau/dispnv50/wndw.h b/drivers/gpu/drm/nouveau/dispnv50/wndw.h index 223cf3f37dae..745304d06af1 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/wndw.h +++ b/drivers/gpu/drm/nouveau/dispnv50/wndw.h @@ -70,15 +70,21 @@ struct nv50_wndw_func { void (*xlut_clr)(struct nv50_wndw *); void (*image_set)(struct nv50_wndw *, struct nv50_wndw_atom *); void (*image_clr)(struct nv50_wndw *); + void (*scale_set)(struct nv50_wndw *, struct nv50_wndw_atom *); void (*update)(struct nv50_wndw *, u32 *interlock); }; extern const struct drm_plane_funcs nv50_wndw; +void base507c_ntfy_reset(struct nouveau_bo *, u32); +int base507c_ntfy_wait_begun(struct nouveau_bo *, u32, struct nvif_device *); + struct nv50_wimm_func { void (*point)(struct nv50_wndw *, struct nv50_wndw_atom *); void (*update)(struct nv50_wndw *, u32 *interlock); }; + +extern const struct nv50_wimm_func curs507a; #endif -- 2.11.0