drm/nouveau/disp: expose head event class
Also fixes vblank interrupts being left enabled when they're not meant to be as a result of races/bugs in previous event handling code. v2: - use ?: (lyude) Signed-off-by: Ben Skeggs <bskeggs@redhat.com> Reviewed-by: Lyude Paul <lyude@redhat.com>
This commit is contained in:
parent
1d4dce2841
commit
ffd2664114
@ -761,7 +761,7 @@ static void nv_crtc_destroy(struct drm_crtc *crtc)
|
||||
nouveau_bo_unmap(nv_crtc->cursor.nvbo);
|
||||
nouveau_bo_unpin(nv_crtc->cursor.nvbo);
|
||||
nouveau_bo_ref(NULL, &nv_crtc->cursor.nvbo);
|
||||
nvif_notify_dtor(&nv_crtc->vblank);
|
||||
nvif_event_dtor(&nv_crtc->vblank);
|
||||
nvif_head_dtor(&nv_crtc->head);
|
||||
kfree(nv_crtc);
|
||||
}
|
||||
@ -1280,13 +1280,13 @@ static const struct drm_plane_funcs nv04_primary_plane_funcs = {
|
||||
DRM_PLANE_NON_ATOMIC_FUNCS,
|
||||
};
|
||||
|
||||
static int nv04_crtc_vblank_handler(struct nvif_notify *notify)
|
||||
static int
|
||||
nv04_crtc_vblank_handler(struct nvif_event *event, void *repv, u32 repc)
|
||||
{
|
||||
struct nouveau_crtc *nv_crtc =
|
||||
container_of(notify, struct nouveau_crtc, vblank);
|
||||
struct nouveau_crtc *nv_crtc = container_of(event, struct nouveau_crtc, vblank);
|
||||
|
||||
drm_crtc_handle_vblank(&nv_crtc->base);
|
||||
return NVIF_NOTIFY_KEEP;
|
||||
return NVIF_EVENT_KEEP;
|
||||
}
|
||||
|
||||
int
|
||||
@ -1346,14 +1346,6 @@ nv04_crtc_create(struct drm_device *dev, int crtc_num)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = nvif_notify_ctor(&disp->disp.object, "kmsVbl", nv04_crtc_vblank_handler,
|
||||
false, NV04_DISP_NTFY_VBLANK,
|
||||
&(struct nvif_notify_head_req_v0) {
|
||||
.head = nv_crtc->index,
|
||||
},
|
||||
sizeof(struct nvif_notify_head_req_v0),
|
||||
sizeof(struct nvif_notify_head_rep_v0),
|
||||
&nv_crtc->vblank);
|
||||
|
||||
return ret;
|
||||
return nvif_head_vblank_event_ctor(&nv_crtc->head, "kmsVbl", nv04_crtc_vblank_handler,
|
||||
false, &nv_crtc->vblank);
|
||||
}
|
||||
|
@ -517,7 +517,7 @@ nv50_head_destroy(struct drm_crtc *crtc)
|
||||
{
|
||||
struct nv50_head *head = nv50_head(crtc);
|
||||
|
||||
nvif_notify_dtor(&head->base.vblank);
|
||||
nvif_event_dtor(&head->base.vblank);
|
||||
nvif_head_dtor(&head->base.head);
|
||||
nv50_lut_fini(&head->olut);
|
||||
drm_crtc_cleanup(crtc);
|
||||
@ -555,15 +555,15 @@ nvd9_head_func = {
|
||||
.late_register = nv50_head_late_register,
|
||||
};
|
||||
|
||||
static int nv50_head_vblank_handler(struct nvif_notify *notify)
|
||||
static int
|
||||
nv50_head_vblank_handler(struct nvif_event *event, void *repv, u32 repc)
|
||||
{
|
||||
struct nouveau_crtc *nv_crtc =
|
||||
container_of(notify, struct nouveau_crtc, vblank);
|
||||
struct nouveau_crtc *nv_crtc = container_of(event, struct nouveau_crtc, vblank);
|
||||
|
||||
if (drm_crtc_handle_vblank(&nv_crtc->base))
|
||||
nv50_crc_handle_vblank(nv50_head(&nv_crtc->base));
|
||||
|
||||
return NVIF_NOTIFY_KEEP;
|
||||
return NVIF_EVENT_KEEP;
|
||||
}
|
||||
|
||||
struct nv50_head *
|
||||
@ -629,14 +629,8 @@ nv50_head_create(struct drm_device *dev, int index)
|
||||
if (ret)
|
||||
return ERR_PTR(ret);
|
||||
|
||||
ret = nvif_notify_ctor(&disp->disp->object, "kmsVbl", nv50_head_vblank_handler,
|
||||
false, NV04_DISP_NTFY_VBLANK,
|
||||
&(struct nvif_notify_head_req_v0) {
|
||||
.head = nv_crtc->index,
|
||||
},
|
||||
sizeof(struct nvif_notify_head_req_v0),
|
||||
sizeof(struct nvif_notify_head_rep_v0),
|
||||
&nv_crtc->vblank);
|
||||
ret = nvif_head_vblank_event_ctor(&head->base.head, "kmsVbl", nv50_head_vblank_handler,
|
||||
false, &nv_crtc->vblank);
|
||||
if (ret)
|
||||
return ERR_PTR(ret);
|
||||
|
||||
|
@ -2,6 +2,5 @@
|
||||
#ifndef __NVIF_CL0046_H__
|
||||
#define __NVIF_CL0046_H__
|
||||
|
||||
#define NV04_DISP_NTFY_VBLANK 0x00
|
||||
#define NV04_DISP_NTFY_CONN 0x01
|
||||
#endif
|
||||
|
@ -52,17 +52,6 @@ struct nvif_notify_rep_v0 {
|
||||
__u8 data[]; /* reply data (below) */
|
||||
};
|
||||
|
||||
struct nvif_notify_head_req_v0 {
|
||||
/* nvif_notify_req ... */
|
||||
__u8 version;
|
||||
__u8 head;
|
||||
__u8 pad02[6];
|
||||
};
|
||||
|
||||
struct nvif_notify_head_rep_v0 {
|
||||
/* nvif_notify_rep ... */
|
||||
};
|
||||
|
||||
struct nvif_notify_conn_req_v0 {
|
||||
/* nvif_notify_req ... */
|
||||
__u8 version;
|
||||
|
@ -2,6 +2,7 @@
|
||||
#ifndef __NVIF_HEAD_H__
|
||||
#define __NVIF_HEAD_H__
|
||||
#include <nvif/object.h>
|
||||
#include <nvif/event.h>
|
||||
struct nvif_disp;
|
||||
|
||||
struct nvif_head {
|
||||
@ -10,4 +11,13 @@ struct nvif_head {
|
||||
|
||||
int nvif_head_ctor(struct nvif_disp *, const char *name, int id, struct nvif_head *);
|
||||
void nvif_head_dtor(struct nvif_head *);
|
||||
|
||||
static inline int
|
||||
nvif_head_id(struct nvif_head *head)
|
||||
{
|
||||
return head->object.handle;
|
||||
}
|
||||
|
||||
int nvif_head_vblank_event_ctor(struct nvif_head *, const char *name, nvif_event_func, bool wait,
|
||||
struct nvif_event *);
|
||||
#endif
|
||||
|
@ -10,6 +10,11 @@ union nvif_head_args {
|
||||
} v0;
|
||||
};
|
||||
|
||||
union nvif_head_event_args {
|
||||
struct nvif_head_event_vn {
|
||||
} vn;
|
||||
};
|
||||
|
||||
#define NVIF_HEAD_V0_SCANOUTPOS 0x00
|
||||
|
||||
union nvif_head_scanoutpos_args {
|
||||
|
@ -29,14 +29,14 @@
|
||||
#include <drm/drm_crtc.h>
|
||||
|
||||
#include <nvif/head.h>
|
||||
#include <nvif/notify.h>
|
||||
#include <nvif/event.h>
|
||||
|
||||
struct nouveau_crtc {
|
||||
struct drm_crtc base;
|
||||
|
||||
struct nvif_head head;
|
||||
int index;
|
||||
struct nvif_notify vblank;
|
||||
struct nvif_event vblank;
|
||||
|
||||
uint32_t dpms_saved_fp_control;
|
||||
uint32_t fp_users;
|
||||
|
@ -52,7 +52,7 @@ nouveau_display_vblank_enable(struct drm_crtc *crtc)
|
||||
struct nouveau_crtc *nv_crtc;
|
||||
|
||||
nv_crtc = nouveau_crtc(crtc);
|
||||
nvif_notify_get(&nv_crtc->vblank);
|
||||
nvif_event_allow(&nv_crtc->vblank);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -63,7 +63,7 @@ nouveau_display_vblank_disable(struct drm_crtc *crtc)
|
||||
struct nouveau_crtc *nv_crtc;
|
||||
|
||||
nv_crtc = nouveau_crtc(crtc);
|
||||
nvif_notify_put(&nv_crtc->vblank);
|
||||
nvif_event_block(&nv_crtc->vblank);
|
||||
}
|
||||
|
||||
static inline int
|
||||
|
@ -26,6 +26,16 @@
|
||||
#include <nvif/class.h>
|
||||
#include <nvif/if0013.h>
|
||||
|
||||
int
|
||||
nvif_head_vblank_event_ctor(struct nvif_head *head, const char *name, nvif_event_func func,
|
||||
bool wait, struct nvif_event *event)
|
||||
{
|
||||
int ret = nvif_event_ctor(&head->object, name ?: "nvifHeadVBlank", nvif_head_id(head),
|
||||
func, wait, NULL, 0, event);
|
||||
NVIF_ERRON(ret, &head->object, "[NEW EVENT:VBLANK]");
|
||||
return ret;
|
||||
}
|
||||
|
||||
void
|
||||
nvif_head_dtor(struct nvif_head *head)
|
||||
{
|
||||
|
@ -57,32 +57,8 @@ nvkm_disp_vblank_init(struct nvkm_event *event, int type, int id)
|
||||
head->func->vblank_get(head);
|
||||
}
|
||||
|
||||
static int
|
||||
nvkm_disp_vblank_ctor(struct nvkm_object *object, void *data, u32 size,
|
||||
struct nvkm_notify *notify)
|
||||
{
|
||||
struct nvkm_disp *disp =
|
||||
container_of(notify->event, typeof(*disp), vblank);
|
||||
union {
|
||||
struct nvif_notify_head_req_v0 v0;
|
||||
} *req = data;
|
||||
int ret = -ENOSYS;
|
||||
|
||||
if (!(ret = nvif_unpack(ret, &data, &size, req->v0, 0, 0, false))) {
|
||||
notify->size = sizeof(struct nvif_notify_head_rep_v0);
|
||||
if (ret = -ENXIO, req->v0.head <= disp->vblank.index_nr) {
|
||||
notify->types = 1;
|
||||
notify->index = req->v0.head;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct nvkm_event_func
|
||||
nvkm_disp_vblank_func = {
|
||||
.ctor = nvkm_disp_vblank_ctor,
|
||||
.init = nvkm_disp_vblank_init,
|
||||
.fini = nvkm_disp_vblank_fini,
|
||||
};
|
||||
@ -132,9 +108,6 @@ nvkm_disp_ntfy(struct nvkm_object *object, u32 type, struct nvkm_event **event)
|
||||
{
|
||||
struct nvkm_disp *disp = nvkm_disp(object->engine);
|
||||
switch (type) {
|
||||
case NV04_DISP_NTFY_VBLANK:
|
||||
*event = &disp->vblank;
|
||||
return 0;
|
||||
case NV04_DISP_NTFY_CONN:
|
||||
*event = &disp->hpd;
|
||||
return 0;
|
||||
|
@ -21,9 +21,27 @@
|
||||
*/
|
||||
#define nvkm_uhead(p) container_of((p), struct nvkm_head, object)
|
||||
#include "head.h"
|
||||
#include <core/event.h>
|
||||
|
||||
#include <nvif/if0013.h>
|
||||
|
||||
#include <nvif/event.h>
|
||||
|
||||
static int
|
||||
nvkm_uhead_uevent(struct nvkm_object *object, void *argv, u32 argc, struct nvkm_uevent *uevent)
|
||||
{
|
||||
struct nvkm_head *head = nvkm_uhead(object);
|
||||
union nvif_head_event_args *args = argv;
|
||||
|
||||
if (!uevent)
|
||||
return 0;
|
||||
if (argc != sizeof(args->vn))
|
||||
return -ENOSYS;
|
||||
|
||||
return nvkm_uevent_add(uevent, &head->disp->vblank, head->id,
|
||||
NVKM_DISP_HEAD_EVENT_VBLANK, NULL);
|
||||
}
|
||||
|
||||
static int
|
||||
nvkm_uhead_mthd_scanoutpos(struct nvkm_head *head, void *argv, u32 argc)
|
||||
{
|
||||
@ -81,6 +99,7 @@ static const struct nvkm_object_func
|
||||
nvkm_uhead = {
|
||||
.dtor = nvkm_uhead_dtor,
|
||||
.mthd = nvkm_uhead_mthd,
|
||||
.uevent = nvkm_uhead_uevent,
|
||||
};
|
||||
|
||||
int
|
||||
|
Loading…
x
Reference in New Issue
Block a user