nouveau-y += core/engine/copy/nve0.o
nouveau-y += core/engine/crypt/nv84.o
nouveau-y += core/engine/crypt/nv98.o
+nouveau-y += core/engine/disp/base.o
nouveau-y += core/engine/disp/nv04.o
nouveau-y += core/engine/disp/nv50.o
nouveau-y += core/engine/disp/nv84.o
--- /dev/null
+/*
+ * Copyright 2013 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.
+ *
+ * Authors: Ben Skeggs
+ */
+
+#include <engine/disp.h>
+
+void
+_nouveau_disp_dtor(struct nouveau_object *object)
+{
+ struct nouveau_disp *disp = (void *)object;
+ nouveau_event_destroy(&disp->vblank);
+ nouveau_engine_destroy(&disp->base);
+}
+
+int
+nouveau_disp_create_(struct nouveau_object *parent,
+ struct nouveau_object *engine,
+ struct nouveau_oclass *oclass, int heads,
+ const char *intname, const char *extname,
+ int length, void **pobject)
+{
+ struct nouveau_disp *disp;
+ int ret;
+
+ ret = nouveau_engine_create_(parent, engine, oclass, true,
+ intname, extname, length, pobject);
+ disp = *pobject;
+ if (ret)
+ return ret;
+
+ return nouveau_event_create(heads, &disp->vblank);
+}
*/
#include <engine/disp.h>
+
+#include <core/event.h>
#include <core/class.h>
struct nv04_disp_priv {
{},
};
+/*******************************************************************************
+ * Display engine implementation
+ ******************************************************************************/
+
+static void
+nv04_disp_vblank_enable(struct nouveau_event *event, int head)
+{
+ nv_wr32(event->priv, 0x600140 + (head * 0x2000) , 0x00000001);
+}
+
static void
-nv04_disp_intr_vblank(struct nv04_disp_priv *priv, int crtc)
+nv04_disp_vblank_disable(struct nouveau_event *event, int head)
{
- struct nouveau_disp *disp = &priv->base;
- if (disp->vblank.notify)
- disp->vblank.notify(disp->vblank.data, crtc);
+ nv_wr32(event->priv, 0x600140 + (head * 0x2000) , 0x00000000);
}
static void
u32 crtc1 = nv_rd32(priv, 0x602100);
if (crtc0 & 0x00000001) {
- nv04_disp_intr_vblank(priv, 0);
+ nouveau_event_trigger(priv->base.vblank, 0);
nv_wr32(priv, 0x600100, 0x00000001);
}
if (crtc1 & 0x00000001) {
- nv04_disp_intr_vblank(priv, 1);
+ nouveau_event_trigger(priv->base.vblank, 1);
nv_wr32(priv, 0x602100, 0x00000001);
}
}
static int
nv04_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
- struct nouveau_oclass *oclass, void *data, u32 size,
- struct nouveau_object **pobject)
+ struct nouveau_oclass *oclass, void *data, u32 size,
+ struct nouveau_object **pobject)
{
struct nv04_disp_priv *priv;
int ret;
- ret = nouveau_disp_create(parent, engine, oclass, "DISPLAY",
+ ret = nouveau_disp_create(parent, engine, oclass, 2, "DISPLAY",
"display", &priv);
*pobject = nv_object(priv);
if (ret)
nv_engine(priv)->sclass = nv04_disp_sclass;
nv_subdev(priv)->intr = nv04_disp_intr;
+ priv->base.vblank->priv = priv;
+ priv->base.vblank->enable = nv04_disp_vblank_enable;
+ priv->base.vblank->disable = nv04_disp_vblank_disable;
return 0;
}
#include <core/handle.h>
#include <core/class.h>
-#include <engine/software.h>
#include <engine/disp.h>
#include <subdev/bios.h>
#include <subdev/bios/pll.h>
#include <subdev/timer.h>
#include <subdev/fb.h>
-#include <subdev/bar.h>
#include <subdev/clock.h>
#include "nv50.h"
* Base display object
******************************************************************************/
+static void
+nv50_disp_base_vblank_enable(struct nouveau_event *event, int head)
+{
+ nv_mask(event->priv, 0x61002c, (1 << head), (1 << head));
+}
+
+static void
+nv50_disp_base_vblank_disable(struct nouveau_event *event, int head)
+{
+ nv_mask(event->priv, 0x61002c, (1 << head), (0 << head));
+}
+
static int
nv50_disp_base_ctor(struct nouveau_object *parent,
struct nouveau_object *engine,
if (ret)
return ret;
+ priv->base.vblank->priv = priv;
+ priv->base.vblank->enable = nv50_disp_base_vblank_enable;
+ priv->base.vblank->disable = nv50_disp_base_vblank_disable;
return nouveau_ramht_new(parent, parent, 0x1000, 0, &base->ramht);
}
}
}
-static void
-nv50_disp_intr_vblank(struct nv50_disp_priv *priv, int crtc)
-{
- struct nouveau_bar *bar = nouveau_bar(priv);
- struct nouveau_disp *disp = &priv->base;
- struct nouveau_software_chan *chan, *temp;
- unsigned long flags;
-
- spin_lock_irqsave(&disp->vblank.lock, flags);
- list_for_each_entry_safe(chan, temp, &disp->vblank.list, vblank.head) {
- if (chan->vblank.crtc != crtc)
- continue;
-
- if (nv_device(priv)->chipset >= 0xc0) {
- nv_wr32(priv, 0x001718, 0x80000000 | chan->vblank.channel);
- bar->flush(bar);
- nv_wr32(priv, 0x06000c,
- upper_32_bits(chan->vblank.offset));
- nv_wr32(priv, 0x060010,
- lower_32_bits(chan->vblank.offset));
- nv_wr32(priv, 0x060014, chan->vblank.value);
- } else {
- nv_wr32(priv, 0x001704, chan->vblank.channel);
- nv_wr32(priv, 0x001710, 0x80000000 | chan->vblank.ctxdma);
- bar->flush(bar);
- if (nv_device(priv)->chipset == 0x50) {
- nv_wr32(priv, 0x001570, chan->vblank.offset);
- nv_wr32(priv, 0x001574, chan->vblank.value);
- } else {
- nv_wr32(priv, 0x060010, chan->vblank.offset);
- nv_wr32(priv, 0x060014, chan->vblank.value);
- }
- }
-
- list_del(&chan->vblank.head);
- if (disp->vblank.put)
- disp->vblank.put(disp->vblank.data, crtc);
- }
- spin_unlock_irqrestore(&disp->vblank.lock, flags);
-
- if (disp->vblank.notify)
- disp->vblank.notify(disp->vblank.data, crtc);
-}
-
static u16
exec_lookup(struct nv50_disp_priv *priv, int head, int outp, u32 ctrl,
struct dcb_output *dcb, u8 *ver, u8 *hdr, u8 *cnt, u8 *len,
}
if (intr1 & 0x00000004) {
- nv50_disp_intr_vblank(priv, 0);
+ nouveau_event_trigger(priv->base.vblank, 0);
nv_wr32(priv, 0x610024, 0x00000004);
intr1 &= ~0x00000004;
}
if (intr1 & 0x00000008) {
- nv50_disp_intr_vblank(priv, 1);
+ nouveau_event_trigger(priv->base.vblank, 1);
nv_wr32(priv, 0x610024, 0x00000008);
intr1 &= ~0x00000008;
}
struct nv50_disp_priv *priv;
int ret;
- ret = nouveau_disp_create(parent, engine, oclass, "PDISP",
+ ret = nouveau_disp_create(parent, engine, oclass, 2, "PDISP",
"display", &priv);
*pobject = nv_object(priv);
if (ret)
priv->dac.power = nv50_dac_power;
priv->dac.sense = nv50_dac_sense;
priv->sor.power = nv50_sor_power;
-
- INIT_LIST_HEAD(&priv->base.vblank.list);
- spin_lock_init(&priv->base.vblank.lock);
return 0;
}
#include <core/parent.h>
#include <core/namedb.h>
+#include <core/engctx.h>
#include <core/ramht.h>
+#include <core/event.h>
#include <engine/dmaobj.h>
#include <engine/disp.h>
struct nv50_disp_priv *priv;
int ret;
- ret = nouveau_disp_create(parent, engine, oclass, "PDISP",
+ ret = nouveau_disp_create(parent, engine, oclass, 2, "PDISP",
"display", &priv);
*pobject = nv_object(priv);
if (ret)
priv->dac.sense = nv50_dac_sense;
priv->sor.power = nv50_sor_power;
priv->sor.hdmi = nv84_hdmi_ctrl;
-
- INIT_LIST_HEAD(&priv->base.vblank.list);
- spin_lock_init(&priv->base.vblank.lock);
return 0;
}
struct nv50_disp_priv *priv;
int ret;
- ret = nouveau_disp_create(parent, engine, oclass, "PDISP",
+ ret = nouveau_disp_create(parent, engine, oclass, 2, "PDISP",
"display", &priv);
*pobject = nv_object(priv);
if (ret)
priv->sor.dp_train_fini = nv94_sor_dp_train_fini;
priv->sor.dp_lnkctl = nv94_sor_dp_lnkctl;
priv->sor.dp_drvctl = nv94_sor_dp_drvctl;
-
- INIT_LIST_HEAD(&priv->base.vblank.list);
- spin_lock_init(&priv->base.vblank.lock);
return 0;
}
struct nv50_disp_priv *priv;
int ret;
- ret = nouveau_disp_create(parent, engine, oclass, "PDISP",
+ ret = nouveau_disp_create(parent, engine, oclass, 2, "PDISP",
"display", &priv);
*pobject = nv_object(priv);
if (ret)
priv->dac.sense = nv50_dac_sense;
priv->sor.power = nv50_sor_power;
priv->sor.hdmi = nv84_hdmi_ctrl;
-
- INIT_LIST_HEAD(&priv->base.vblank.list);
- spin_lock_init(&priv->base.vblank.lock);
return 0;
}
struct nv50_disp_priv *priv;
int ret;
- ret = nouveau_disp_create(parent, engine, oclass, "PDISP",
+ ret = nouveau_disp_create(parent, engine, oclass, 2, "PDISP",
"display", &priv);
*pobject = nv_object(priv);
if (ret)
priv->sor.dp_train_fini = nv94_sor_dp_train_fini;
priv->sor.dp_lnkctl = nv94_sor_dp_lnkctl;
priv->sor.dp_drvctl = nv94_sor_dp_drvctl;
-
- INIT_LIST_HEAD(&priv->base.vblank.list);
- spin_lock_init(&priv->base.vblank.lock);
return 0;
}
#include <core/handle.h>
#include <core/class.h>
-#include <engine/software.h>
#include <engine/disp.h>
#include <subdev/timer.h>
#include <subdev/fb.h>
-#include <subdev/bar.h>
#include <subdev/clock.h>
#include <subdev/bios.h>
* Base display object
******************************************************************************/
+static void
+nvd0_disp_base_vblank_enable(struct nouveau_event *event, int head)
+{
+ nv_mask(event->priv, 0x6100c0 + (head * 0x800), 0x00000001, 0x00000001);
+}
+
+static void
+nvd0_disp_base_vblank_disable(struct nouveau_event *event, int head)
+{
+ nv_mask(event->priv, 0x6100c0 + (head * 0x800), 0x00000001, 0x00000000);
+}
+
static int
nvd0_disp_base_ctor(struct nouveau_object *parent,
struct nouveau_object *engine,
if (ret)
return ret;
+ priv->base.vblank->priv = priv;
+ priv->base.vblank->enable = nvd0_disp_base_vblank_enable;
+ priv->base.vblank->disable = nvd0_disp_base_vblank_disable;
+
return nouveau_ramht_new(parent, parent, 0x1000, 0, &base->ramht);
}
nv_wr32(priv, 0x6101d0, 0x80000000);
}
-static void
-nvd0_disp_intr_vblank(struct nv50_disp_priv *priv, int crtc)
-{
- struct nouveau_bar *bar = nouveau_bar(priv);
- struct nouveau_disp *disp = &priv->base;
- struct nouveau_software_chan *chan, *temp;
- unsigned long flags;
-
- spin_lock_irqsave(&disp->vblank.lock, flags);
- list_for_each_entry_safe(chan, temp, &disp->vblank.list, vblank.head) {
- if (chan->vblank.crtc != crtc)
- continue;
-
- nv_wr32(priv, 0x001718, 0x80000000 | chan->vblank.channel);
- bar->flush(bar);
- nv_wr32(priv, 0x06000c, upper_32_bits(chan->vblank.offset));
- nv_wr32(priv, 0x060010, lower_32_bits(chan->vblank.offset));
- nv_wr32(priv, 0x060014, chan->vblank.value);
-
- list_del(&chan->vblank.head);
- if (disp->vblank.put)
- disp->vblank.put(disp->vblank.data, crtc);
- }
- spin_unlock_irqrestore(&disp->vblank.lock, flags);
-
- if (disp->vblank.notify)
- disp->vblank.notify(disp->vblank.data, crtc);
-}
-
void
nvd0_disp_intr(struct nouveau_subdev *subdev)
{
if (mask & intr) {
u32 stat = nv_rd32(priv, 0x6100bc + (i * 0x800));
if (stat & 0x00000001)
- nvd0_disp_intr_vblank(priv, i);
+ nouveau_event_trigger(priv->base.vblank, i);
nv_mask(priv, 0x6100bc + (i * 0x800), 0, 0);
nv_rd32(priv, 0x6100c0 + (i * 0x800));
}
struct nouveau_object **pobject)
{
struct nv50_disp_priv *priv;
+ int heads = nv_rd32(parent, 0x022448);
int ret;
- ret = nouveau_disp_create(parent, engine, oclass, "PDISP",
- "display", &priv);
+ ret = nouveau_disp_create(parent, engine, oclass, heads,
+ "PDISP", "display", &priv);
*pobject = nv_object(priv);
if (ret)
return ret;
nv_engine(priv)->cclass = &nv50_disp_cclass;
nv_subdev(priv)->intr = nvd0_disp_intr;
priv->sclass = nvd0_disp_sclass;
- priv->head.nr = nv_rd32(priv, 0x022448);
+ priv->head.nr = heads;
priv->dac.nr = 3;
priv->sor.nr = 4;
priv->dac.power = nv50_dac_power;
priv->sor.dp_train_fini = nv94_sor_dp_train_fini;
priv->sor.dp_lnkctl = nvd0_sor_dp_lnkctl;
priv->sor.dp_drvctl = nvd0_sor_dp_drvctl;
-
- INIT_LIST_HEAD(&priv->base.vblank.list);
- spin_lock_init(&priv->base.vblank.lock);
return 0;
}
struct nouveau_object **pobject)
{
struct nv50_disp_priv *priv;
+ int heads = nv_rd32(parent, 0x022448);
int ret;
- ret = nouveau_disp_create(parent, engine, oclass, "PDISP",
- "display", &priv);
+ ret = nouveau_disp_create(parent, engine, oclass, heads,
+ "PDISP", "display", &priv);
*pobject = nv_object(priv);
if (ret)
return ret;
nv_engine(priv)->cclass = &nv50_disp_cclass;
nv_subdev(priv)->intr = nvd0_disp_intr;
priv->sclass = nve0_disp_sclass;
- priv->head.nr = nv_rd32(priv, 0x022448);
+ priv->head.nr = heads;
priv->dac.nr = 3;
priv->sor.nr = 4;
priv->dac.power = nv50_dac_power;
priv->sor.dp_train_fini = nv94_sor_dp_train_fini;
priv->sor.dp_lnkctl = nvd0_sor_dp_lnkctl;
priv->sor.dp_drvctl = nvd0_sor_dp_drvctl;
-
- INIT_LIST_HEAD(&priv->base.vblank.list);
- spin_lock_init(&priv->base.vblank.lock);
return 0;
}
#include <core/namedb.h>
#include <core/handle.h>
#include <core/gpuobj.h>
+#include <core/event.h>
+
+#include <subdev/bar.h>
#include <engine/software.h>
#include <engine/disp.h>
{
struct nv50_software_chan *chan = (void *)nv_engctx(object->parent);
struct nouveau_disp *disp = nouveau_disp(object);
- unsigned long flags;
u32 crtc = *(u32 *)args;
-
if (crtc > 1)
return -EINVAL;
- disp->vblank.get(disp->vblank.data, crtc);
-
- spin_lock_irqsave(&disp->vblank.lock, flags);
- list_add(&chan->base.vblank.head, &disp->vblank.list);
- chan->base.vblank.crtc = crtc;
- spin_unlock_irqrestore(&disp->vblank.lock, flags);
+ nouveau_event_get(disp->vblank, crtc, &chan->base.vblank.event);
return 0;
}
* software context
******************************************************************************/
+static int
+nv50_software_vblsem_release(struct nouveau_eventh *event, int head)
+{
+ struct nouveau_software_chan *chan =
+ container_of(event, struct nouveau_software_chan, vblank.event);
+ struct nv50_software_priv *priv = (void *)nv_object(chan)->engine;
+ struct nouveau_bar *bar = nouveau_bar(priv);
+
+ nv_wr32(priv, 0x001704, chan->vblank.channel);
+ nv_wr32(priv, 0x001710, 0x80000000 | chan->vblank.ctxdma);
+ bar->flush(bar);
+
+ if (nv_device(priv)->chipset == 0x50) {
+ nv_wr32(priv, 0x001570, chan->vblank.offset);
+ nv_wr32(priv, 0x001574, chan->vblank.value);
+ } else {
+ nv_wr32(priv, 0x060010, chan->vblank.offset);
+ nv_wr32(priv, 0x060014, chan->vblank.value);
+ }
+
+ return NVKM_EVENT_DROP;
+}
+
static int
nv50_software_context_ctor(struct nouveau_object *parent,
struct nouveau_object *engine,
return ret;
chan->base.vblank.channel = nv_gpuobj(parent->parent)->addr >> 12;
+ chan->base.vblank.event.func = nv50_software_vblsem_release;
return 0;
}
static int
nv50_software_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
- struct nouveau_oclass *oclass, void *data, u32 size,
- struct nouveau_object **pobject)
+ struct nouveau_oclass *oclass, void *data, u32 size,
+ struct nouveau_object **pobject)
{
struct nv50_software_priv *priv;
int ret;
#include <core/os.h>
#include <core/class.h>
#include <core/engctx.h>
+#include <core/event.h>
+
+#include <subdev/bar.h>
#include <engine/software.h>
#include <engine/disp.h>
{
struct nvc0_software_chan *chan = (void *)nv_engctx(object->parent);
struct nouveau_disp *disp = nouveau_disp(object);
- unsigned long flags;
u32 crtc = *(u32 *)args;
if ((nv_device(object)->card_type < NV_E0 && crtc > 1) || crtc > 3)
return -EINVAL;
- disp->vblank.get(disp->vblank.data, crtc);
-
- spin_lock_irqsave(&disp->vblank.lock, flags);
- list_add(&chan->base.vblank.head, &disp->vblank.list);
- chan->base.vblank.crtc = crtc;
- spin_unlock_irqrestore(&disp->vblank.lock, flags);
+ nouveau_event_get(disp->vblank, crtc, &chan->base.vblank.event);
return 0;
}
* software context
******************************************************************************/
+static int
+nvc0_software_vblsem_release(struct nouveau_eventh *event, int head)
+{
+ struct nouveau_software_chan *chan =
+ container_of(event, struct nouveau_software_chan, vblank.event);
+ struct nvc0_software_priv *priv = (void *)nv_object(chan)->engine;
+ struct nouveau_bar *bar = nouveau_bar(priv);
+
+ nv_wr32(priv, 0x001718, 0x80000000 | chan->vblank.channel);
+ bar->flush(bar);
+ nv_wr32(priv, 0x06000c, upper_32_bits(chan->vblank.offset));
+ nv_wr32(priv, 0x060010, lower_32_bits(chan->vblank.offset));
+ nv_wr32(priv, 0x060014, chan->vblank.value);
+
+ return NVKM_EVENT_DROP;
+}
+
static int
nvc0_software_context_ctor(struct nouveau_object *parent,
struct nouveau_object *engine,
return ret;
chan->base.vblank.channel = nv_gpuobj(parent->parent)->addr >> 12;
+ chan->base.vblank.event.func = nvc0_software_vblsem_release;
return 0;
}
#include <core/object.h>
#include <core/engine.h>
#include <core/device.h>
+#include <core/event.h>
struct nouveau_disp {
struct nouveau_engine base;
-
- struct {
- struct list_head list;
- spinlock_t lock;
- void (*notify)(void *, int);
- void (*get)(void *, int);
- void (*put)(void *, int);
- void *data;
- } vblank;
+ struct nouveau_event *vblank;
};
static inline struct nouveau_disp *
return (void *)nv_device(obj)->subdev[NVDEV_ENGINE_DISP];
}
-#define nouveau_disp_create(p,e,c,i,x,d) \
- nouveau_engine_create((p), (e), (c), true, (i), (x), (d))
-#define nouveau_disp_destroy(d) \
- nouveau_engine_destroy(&(d)->base)
+#define nouveau_disp_create(p,e,c,h,i,x,d) \
+ nouveau_disp_create_((p), (e), (c), (h), (i), (x), \
+ sizeof(**d), (void **)d)
+#define nouveau_disp_destroy(d) ({ \
+ struct nouveau_disp *disp = (d); \
+ _nouveau_disp_dtor(nv_object(disp)); \
+})
#define nouveau_disp_init(d) \
nouveau_engine_init(&(d)->base)
#define nouveau_disp_fini(d,s) \
nouveau_engine_fini(&(d)->base, (s))
-#define _nouveau_disp_dtor _nouveau_engine_dtor
+int nouveau_disp_create_(struct nouveau_object *, struct nouveau_object *,
+ struct nouveau_oclass *, int heads,
+ const char *, const char *, int, void **);
+void _nouveau_disp_dtor(struct nouveau_object *);
#define _nouveau_disp_init _nouveau_engine_init
#define _nouveau_disp_fini _nouveau_engine_fini
#include <core/engine.h>
#include <core/engctx.h>
+#include <core/event.h>
struct nouveau_software_chan {
struct nouveau_engctx base;
struct {
- struct list_head head;
+ struct nouveau_eventh event;
u32 channel;
u32 ctxdma;
u64 offset;
u32 value;
- u32 crtc;
} vblank;
int (*flip)(void *);
#include <subdev/gpio.h>
#include <engine/disp.h>
+#include <core/class.h>
+
static void
nouveau_user_framebuffer_destroy(struct drm_framebuffer *drm_fb)
{
disp->fini(dev);
}
-static void
-nouveau_display_vblank_notify(void *data, int crtc)
-{
- drm_handle_vblank(data, crtc);
-}
-
-static void
-nouveau_display_vblank_get(void *data, int crtc)
-{
- drm_vblank_get(data, crtc);
-}
-
-static void
-nouveau_display_vblank_put(void *data, int crtc)
-{
- drm_vblank_put(data, crtc);
-}
-
int
nouveau_display_create(struct drm_device *dev)
{
struct nouveau_drm *drm = nouveau_drm(dev);
- struct nouveau_disp *pdisp = nouveau_disp(drm->device);
struct nouveau_display *disp;
u32 pclass = dev->pdev->class >> 8;
int ret, gen;
if (!disp)
return -ENOMEM;
- pdisp->vblank.data = dev;
- pdisp->vblank.notify = nouveau_display_vblank_notify;
- pdisp->vblank.get = nouveau_display_vblank_get;
- pdisp->vblank.put = nouveau_display_vblank_put;
-
drm_mode_config_init(dev);
drm_mode_create_scaling_mode_property(dev);
drm_mode_create_dvi_i_properties(dev);
}
}
-int
-nouveau_vblank_enable(struct drm_device *dev, int crtc)
-{
- struct nouveau_device *device = nouveau_dev(dev);
-
- if (device->card_type >= NV_D0)
- nv_mask(device, 0x6100c0 + (crtc * 0x800), 1, 1);
- else
- if (device->card_type >= NV_50)
- nv_mask(device, NV50_PDISPLAY_INTR_EN_1, 0,
- NV50_PDISPLAY_INTR_EN_1_VBLANK_CRTC_(crtc));
- else
- NVWriteCRTC(dev, crtc, NV_PCRTC_INTR_EN_0,
- NV_PCRTC_INTR_0_VBLANK);
-
- return 0;
-}
-
-void
-nouveau_vblank_disable(struct drm_device *dev, int crtc)
-{
- struct nouveau_device *device = nouveau_dev(dev);
-
- if (device->card_type >= NV_D0)
- nv_mask(device, 0x6100c0 + (crtc * 0x800), 1, 0);
- else
- if (device->card_type >= NV_50)
- nv_mask(device, NV50_PDISPLAY_INTR_EN_1,
- NV50_PDISPLAY_INTR_EN_1_VBLANK_CRTC_(crtc), 0);
- else
- NVWriteCRTC(dev, crtc, NV_PCRTC_INTR_EN_0, 0);
-}
-
static int
nouveau_page_flip_reserve(struct nouveau_bo *old_bo,
struct nouveau_bo *new_bo)
int nouveau_display_suspend(struct drm_device *dev);
void nouveau_display_resume(struct drm_device *dev);
-int nouveau_vblank_enable(struct drm_device *dev, int crtc);
-void nouveau_vblank_disable(struct drm_device *dev, int crtc);
-
int nouveau_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb,
struct drm_pending_vblank_event *event);
int nouveau_finish_page_flip(struct nouveau_channel *,
#include <subdev/device.h>
#include <subdev/vm.h>
+#include <engine/disp.h>
+
#include "nouveau_drm.h"
#include "nouveau_irq.h"
#include "nouveau_dma.h"
static struct drm_driver driver;
+static int
+nouveau_drm_vblank_enable(struct drm_device *dev, int head)
+{
+ struct nouveau_drm *drm = nouveau_drm(dev);
+ struct nouveau_disp *pdisp = nouveau_disp(drm->device);
+ nouveau_event_get(pdisp->vblank, head, &drm->vblank);
+ return 0;
+}
+
+static void
+nouveau_drm_vblank_disable(struct drm_device *dev, int head)
+{
+ struct nouveau_drm *drm = nouveau_drm(dev);
+ struct nouveau_disp *pdisp = nouveau_disp(drm->device);
+ nouveau_event_put(pdisp->vblank, head, &drm->vblank);
+}
+
+static int
+nouveau_drm_vblank_handler(struct nouveau_eventh *event, int head)
+{
+ struct nouveau_drm *drm =
+ container_of(event, struct nouveau_drm, vblank);
+ drm_handle_vblank(drm->dev, head);
+ return NVKM_EVENT_KEEP;
+}
+
static u64
nouveau_name(struct pci_dev *pdev)
{
dev->dev_private = drm;
drm->dev = dev;
+ drm->vblank.func = nouveau_drm_vblank_handler;
INIT_LIST_HEAD(&drm->clients);
spin_lock_init(&drm->tile.lock);
.irq_handler = nouveau_irq_handler,
.get_vblank_counter = drm_vblank_count,
- .enable_vblank = nouveau_vblank_enable,
- .disable_vblank = nouveau_vblank_disable,
+ .enable_vblank = nouveau_drm_vblank_enable,
+ .disable_vblank = nouveau_drm_vblank_disable,
.ioctls = nouveau_ioctls,
.fops = &nouveau_driver_fops,
#define DRIVER_PATCHLEVEL 0
#include <core/client.h>
+#include <core/event.h>
#include <subdev/vm.h>
struct nvbios vbios;
struct nouveau_display *display;
struct backlight_device *backlight;
+ struct nouveau_eventh vblank;
/* power management */
struct nouveau_pm *pm;