drm/nouveau/disp: implement nvif event sources for vblank/connector notifiers
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
This commit is contained in:
parent
b76f15295e
commit
80bc340b3d
11 changed files with 47 additions and 20 deletions
|
@ -24,6 +24,7 @@
|
||||||
|
|
||||||
#include <core/os.h>
|
#include <core/os.h>
|
||||||
#include <nvif/unpack.h>
|
#include <nvif/unpack.h>
|
||||||
|
#include <nvif/class.h>
|
||||||
#include <nvif/event.h>
|
#include <nvif/event.h>
|
||||||
|
|
||||||
#include "priv.h"
|
#include "priv.h"
|
||||||
|
@ -92,6 +93,24 @@ nouveau_disp_hpd_func = {
|
||||||
.ctor = nouveau_disp_hpd_ctor
|
.ctor = nouveau_disp_hpd_ctor
|
||||||
};
|
};
|
||||||
|
|
||||||
|
int
|
||||||
|
nouveau_disp_ntfy(struct nouveau_object *object, u32 type,
|
||||||
|
struct nvkm_event **event)
|
||||||
|
{
|
||||||
|
struct nouveau_disp *disp = (void *)object->engine;
|
||||||
|
switch (type) {
|
||||||
|
case NV04_DISP_NTFY_VBLANK:
|
||||||
|
*event = &disp->vblank;
|
||||||
|
return 0;
|
||||||
|
case NV04_DISP_NTFY_CONN:
|
||||||
|
*event = &disp->hpd;
|
||||||
|
return 0;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
_nouveau_disp_fini(struct nouveau_object *object, bool suspend)
|
_nouveau_disp_fini(struct nouveau_object *object, bool suspend)
|
||||||
{
|
{
|
||||||
|
|
|
@ -112,6 +112,7 @@ nv04_disp_ofuncs = {
|
||||||
.init = nouveau_object_init,
|
.init = nouveau_object_init,
|
||||||
.fini = nouveau_object_fini,
|
.fini = nouveau_object_fini,
|
||||||
.mthd = nv04_disp_mthd,
|
.mthd = nv04_disp_mthd,
|
||||||
|
.ntfy = nouveau_disp_ntfy,
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct nouveau_oclass
|
static struct nouveau_oclass
|
||||||
|
|
|
@ -1142,6 +1142,7 @@ nv50_disp_base_ofuncs = {
|
||||||
.init = nv50_disp_base_init,
|
.init = nv50_disp_base_init,
|
||||||
.fini = nv50_disp_base_fini,
|
.fini = nv50_disp_base_fini,
|
||||||
.mthd = nv50_disp_base_mthd,
|
.mthd = nv50_disp_base_mthd,
|
||||||
|
.ntfy = nouveau_disp_ntfy,
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct nouveau_oclass
|
static struct nouveau_oclass
|
||||||
|
|
|
@ -716,6 +716,7 @@ nvd0_disp_base_ofuncs = {
|
||||||
.init = nvd0_disp_base_init,
|
.init = nvd0_disp_base_init,
|
||||||
.fini = nvd0_disp_base_fini,
|
.fini = nvd0_disp_base_fini,
|
||||||
.mthd = nv50_disp_base_mthd,
|
.mthd = nv50_disp_base_mthd,
|
||||||
|
.ntfy = nouveau_disp_ntfy,
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct nouveau_oclass
|
static struct nouveau_oclass
|
||||||
|
|
|
@ -42,5 +42,6 @@ extern struct nouveau_oclass *nvkm_connector_oclass;
|
||||||
|
|
||||||
int nouveau_disp_vblank_ctor(void *data, u32 size, struct nvkm_notify *);
|
int nouveau_disp_vblank_ctor(void *data, u32 size, struct nvkm_notify *);
|
||||||
void nouveau_disp_vblank(struct nouveau_disp *, int head);
|
void nouveau_disp_vblank(struct nouveau_disp *, int head);
|
||||||
|
int nouveau_disp_ntfy(struct nouveau_object *, u32, struct nvkm_event **);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -100,7 +100,7 @@ static void
|
||||||
nouveau_connector_destroy(struct drm_connector *connector)
|
nouveau_connector_destroy(struct drm_connector *connector)
|
||||||
{
|
{
|
||||||
struct nouveau_connector *nv_connector = nouveau_connector(connector);
|
struct nouveau_connector *nv_connector = nouveau_connector(connector);
|
||||||
nvkm_notify_fini(&nv_connector->hpd);
|
nvif_notify_fini(&nv_connector->hpd);
|
||||||
kfree(nv_connector->edid);
|
kfree(nv_connector->edid);
|
||||||
drm_connector_unregister(connector);
|
drm_connector_unregister(connector);
|
||||||
drm_connector_cleanup(connector);
|
drm_connector_cleanup(connector);
|
||||||
|
@ -937,7 +937,7 @@ nouveau_connector_funcs_dp = {
|
||||||
};
|
};
|
||||||
|
|
||||||
static int
|
static int
|
||||||
nouveau_connector_hotplug(struct nvkm_notify *notify)
|
nouveau_connector_hotplug(struct nvif_notify *notify)
|
||||||
{
|
{
|
||||||
struct nouveau_connector *nv_connector =
|
struct nouveau_connector *nv_connector =
|
||||||
container_of(notify, typeof(*nv_connector), hpd);
|
container_of(notify, typeof(*nv_connector), hpd);
|
||||||
|
@ -959,7 +959,7 @@ nouveau_connector_hotplug(struct nvkm_notify *notify)
|
||||||
drm_helper_hpd_irq_event(connector->dev);
|
drm_helper_hpd_irq_event(connector->dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
return NVKM_NOTIFY_KEEP;
|
return NVIF_NOTIFY_KEEP;
|
||||||
}
|
}
|
||||||
|
|
||||||
static ssize_t
|
static ssize_t
|
||||||
|
@ -1029,7 +1029,6 @@ nouveau_connector_create(struct drm_device *dev, int index)
|
||||||
struct nouveau_drm *drm = nouveau_drm(dev);
|
struct nouveau_drm *drm = nouveau_drm(dev);
|
||||||
struct nouveau_display *disp = nouveau_display(dev);
|
struct nouveau_display *disp = nouveau_display(dev);
|
||||||
struct nouveau_connector *nv_connector = NULL;
|
struct nouveau_connector *nv_connector = NULL;
|
||||||
struct nouveau_disp *pdisp = nvkm_disp(&drm->device);
|
|
||||||
struct drm_connector *connector;
|
struct drm_connector *connector;
|
||||||
int type, ret = 0;
|
int type, ret = 0;
|
||||||
bool dummy;
|
bool dummy;
|
||||||
|
@ -1215,7 +1214,8 @@ nouveau_connector_create(struct drm_device *dev, int index)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = nvkm_notify_init(&pdisp->hpd, nouveau_connector_hotplug, true,
|
ret = nvif_notify_init(&disp->disp, NULL, nouveau_connector_hotplug,
|
||||||
|
true, NV04_DISP_NTFY_CONN,
|
||||||
&(struct nvif_notify_conn_req_v0) {
|
&(struct nvif_notify_conn_req_v0) {
|
||||||
.mask = NVIF_NOTIFY_CONN_V0_ANY,
|
.mask = NVIF_NOTIFY_CONN_V0_ANY,
|
||||||
.conn = index,
|
.conn = index,
|
||||||
|
|
|
@ -27,6 +27,8 @@
|
||||||
#ifndef __NOUVEAU_CONNECTOR_H__
|
#ifndef __NOUVEAU_CONNECTOR_H__
|
||||||
#define __NOUVEAU_CONNECTOR_H__
|
#define __NOUVEAU_CONNECTOR_H__
|
||||||
|
|
||||||
|
#include <nvif/notify.h>
|
||||||
|
|
||||||
#include <drm/drm_edid.h>
|
#include <drm/drm_edid.h>
|
||||||
#include <drm/drm_dp_helper.h>
|
#include <drm/drm_dp_helper.h>
|
||||||
#include "nouveau_crtc.h"
|
#include "nouveau_crtc.h"
|
||||||
|
@ -63,7 +65,7 @@ struct nouveau_connector {
|
||||||
u8 index;
|
u8 index;
|
||||||
u8 *dcb;
|
u8 *dcb;
|
||||||
|
|
||||||
struct nvkm_notify hpd;
|
struct nvif_notify hpd;
|
||||||
|
|
||||||
struct drm_dp_aux aux;
|
struct drm_dp_aux aux;
|
||||||
|
|
||||||
|
|
|
@ -27,11 +27,13 @@
|
||||||
#ifndef __NOUVEAU_CRTC_H__
|
#ifndef __NOUVEAU_CRTC_H__
|
||||||
#define __NOUVEAU_CRTC_H__
|
#define __NOUVEAU_CRTC_H__
|
||||||
|
|
||||||
|
#include <nvif/notify.h>
|
||||||
|
|
||||||
struct nouveau_crtc {
|
struct nouveau_crtc {
|
||||||
struct drm_crtc base;
|
struct drm_crtc base;
|
||||||
|
|
||||||
int index;
|
int index;
|
||||||
struct nvkm_notify vblank;
|
struct nvif_notify vblank;
|
||||||
|
|
||||||
uint32_t dpms_saved_fp_control;
|
uint32_t dpms_saved_fp_control;
|
||||||
uint32_t fp_users;
|
uint32_t fp_users;
|
||||||
|
|
|
@ -42,12 +42,12 @@
|
||||||
#include <nvif/event.h>
|
#include <nvif/event.h>
|
||||||
|
|
||||||
static int
|
static int
|
||||||
nouveau_display_vblank_handler(struct nvkm_notify *notify)
|
nouveau_display_vblank_handler(struct nvif_notify *notify)
|
||||||
{
|
{
|
||||||
struct nouveau_crtc *nv_crtc =
|
struct nouveau_crtc *nv_crtc =
|
||||||
container_of(notify, typeof(*nv_crtc), vblank);
|
container_of(notify, typeof(*nv_crtc), vblank);
|
||||||
drm_handle_vblank(nv_crtc->base.dev, nv_crtc->index);
|
drm_handle_vblank(nv_crtc->base.dev, nv_crtc->index);
|
||||||
return NVKM_NOTIFY_KEEP;
|
return NVIF_NOTIFY_KEEP;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
|
@ -57,7 +57,7 @@ nouveau_display_vblank_enable(struct drm_device *dev, int head)
|
||||||
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
|
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
|
||||||
struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
|
struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
|
||||||
if (nv_crtc->index == head) {
|
if (nv_crtc->index == head) {
|
||||||
nvkm_notify_get(&nv_crtc->vblank);
|
nvif_notify_get(&nv_crtc->vblank);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -71,7 +71,7 @@ nouveau_display_vblank_disable(struct drm_device *dev, int head)
|
||||||
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
|
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
|
||||||
struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
|
struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
|
||||||
if (nv_crtc->index == head) {
|
if (nv_crtc->index == head) {
|
||||||
nvkm_notify_put(&nv_crtc->vblank);
|
nvif_notify_put(&nv_crtc->vblank);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -172,22 +172,22 @@ nouveau_display_vblank_fini(struct drm_device *dev)
|
||||||
|
|
||||||
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
|
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
|
||||||
struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
|
struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
|
||||||
nvkm_notify_fini(&nv_crtc->vblank);
|
nvif_notify_fini(&nv_crtc->vblank);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
nouveau_display_vblank_init(struct drm_device *dev)
|
nouveau_display_vblank_init(struct drm_device *dev)
|
||||||
{
|
{
|
||||||
struct nouveau_drm *drm = nouveau_drm(dev);
|
struct nouveau_display *disp = nouveau_display(dev);
|
||||||
struct nouveau_disp *pdisp = nvkm_disp(&drm->device);
|
|
||||||
struct drm_crtc *crtc;
|
struct drm_crtc *crtc;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
|
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
|
||||||
struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
|
struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
|
||||||
ret = nvkm_notify_init(&pdisp->vblank,
|
ret = nvif_notify_init(&disp->disp, NULL,
|
||||||
nouveau_display_vblank_handler, false,
|
nouveau_display_vblank_handler, false,
|
||||||
|
NV04_DISP_NTFY_VBLANK,
|
||||||
&(struct nvif_notify_head_req_v0) {
|
&(struct nvif_notify_head_req_v0) {
|
||||||
.head = nv_crtc->index,
|
.head = nv_crtc->index,
|
||||||
},
|
},
|
||||||
|
@ -371,7 +371,7 @@ nouveau_display_init(struct drm_device *dev)
|
||||||
/* enable hotplug interrupts */
|
/* enable hotplug interrupts */
|
||||||
list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
|
list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
|
||||||
struct nouveau_connector *conn = nouveau_connector(connector);
|
struct nouveau_connector *conn = nouveau_connector(connector);
|
||||||
nvkm_notify_get(&conn->hpd);
|
nvif_notify_get(&conn->hpd);
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -391,7 +391,7 @@ nouveau_display_fini(struct drm_device *dev)
|
||||||
/* disable hotplug interrupts */
|
/* disable hotplug interrupts */
|
||||||
list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
|
list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
|
||||||
struct nouveau_connector *conn = nouveau_connector(connector);
|
struct nouveau_connector *conn = nouveau_connector(connector);
|
||||||
nvkm_notify_put(&conn->hpd);
|
nvif_notify_put(&conn->hpd);
|
||||||
}
|
}
|
||||||
|
|
||||||
drm_kms_helper_poll_disable(dev);
|
drm_kms_helper_poll_disable(dev);
|
||||||
|
|
|
@ -343,6 +343,9 @@ struct kepler_channel_gpfifo_a_v0 {
|
||||||
* legacy display
|
* legacy display
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
|
|
||||||
|
#define NV04_DISP_NTFY_VBLANK 0x00
|
||||||
|
#define NV04_DISP_NTFY_CONN 0x01
|
||||||
|
|
||||||
struct nv04_disp_mthd_v0 {
|
struct nv04_disp_mthd_v0 {
|
||||||
__u8 version;
|
__u8 version;
|
||||||
#define NV04_DISP_SCANOUTPOS 0x00
|
#define NV04_DISP_SCANOUTPOS 0x00
|
||||||
|
@ -365,7 +368,6 @@ struct nv04_disp_scanoutpos_v0 {
|
||||||
__u16 hline;
|
__u16 hline;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
* display
|
* display
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
|
|
|
@ -54,13 +54,11 @@ void nvif_device_ref(struct nvif_device *, struct nvif_device **);
|
||||||
|
|
||||||
#include <engine/device.h>
|
#include <engine/device.h>
|
||||||
#include <engine/fifo.h>
|
#include <engine/fifo.h>
|
||||||
#include <engine/disp.h>
|
|
||||||
#include <engine/graph.h>
|
#include <engine/graph.h>
|
||||||
#include <engine/software.h>
|
#include <engine/software.h>
|
||||||
|
|
||||||
#define nvkm_fifo(a) nouveau_fifo(nvkm_device(a))
|
#define nvkm_fifo(a) nouveau_fifo(nvkm_device(a))
|
||||||
#define nvkm_fifo_chan(a) ((struct nouveau_fifo_chan *)nvkm_object(a))
|
#define nvkm_fifo_chan(a) ((struct nouveau_fifo_chan *)nvkm_object(a))
|
||||||
#define nvkm_disp(a) nouveau_disp(nvkm_device(a))
|
|
||||||
#define nvkm_gr(a) ((struct nouveau_graph *)nouveau_engine(nvkm_object(a), NVDEV_ENGINE_GR))
|
#define nvkm_gr(a) ((struct nouveau_graph *)nouveau_engine(nvkm_object(a), NVDEV_ENGINE_GR))
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in a new issue