drm/nouveau/disp: expose conn event class
This removes some now-unnecessary nesting of workqueues. v2: - use ?: (lyude) Signed-off-by: Ben Skeggs <bskeggs@redhat.com> Reviewed-by: Lyude Paul <lyude@redhat.com>
This commit is contained in:
parent
ffd2664114
commit
773eb04d14
@ -2,6 +2,7 @@
|
||||
#ifndef __NVIF_CONN_H__
|
||||
#define __NVIF_CONN_H__
|
||||
#include <nvif/object.h>
|
||||
#include <nvif/event.h>
|
||||
struct nvif_disp;
|
||||
|
||||
struct nvif_conn {
|
||||
@ -11,8 +12,17 @@ struct nvif_conn {
|
||||
int nvif_conn_ctor(struct nvif_disp *, const char *name, int id, struct nvif_conn *);
|
||||
void nvif_conn_dtor(struct nvif_conn *);
|
||||
|
||||
static inline int
|
||||
nvif_conn_id(struct nvif_conn *conn)
|
||||
{
|
||||
return conn->object.handle;
|
||||
}
|
||||
|
||||
#define NVIF_CONN_HPD_STATUS_UNSUPPORTED 0 /* negative if query fails */
|
||||
#define NVIF_CONN_HPD_STATUS_NOT_PRESENT 1
|
||||
#define NVIF_CONN_HPD_STATUS_PRESENT 2
|
||||
int nvif_conn_hpd_status(struct nvif_conn *);
|
||||
|
||||
int nvif_conn_event_ctor(struct nvif_conn *, const char *name, nvif_event_func, u8 types,
|
||||
struct nvif_event *);
|
||||
#endif
|
||||
|
@ -52,25 +52,6 @@ struct nvif_notify_rep_v0 {
|
||||
__u8 data[]; /* reply data (below) */
|
||||
};
|
||||
|
||||
struct nvif_notify_conn_req_v0 {
|
||||
/* nvif_notify_req ... */
|
||||
__u8 version;
|
||||
#define NVIF_NOTIFY_CONN_V0_PLUG 0x01
|
||||
#define NVIF_NOTIFY_CONN_V0_UNPLUG 0x02
|
||||
#define NVIF_NOTIFY_CONN_V0_IRQ 0x04
|
||||
#define NVIF_NOTIFY_CONN_V0_ANY 0x07
|
||||
__u8 mask;
|
||||
__u8 conn;
|
||||
__u8 pad03[5];
|
||||
};
|
||||
|
||||
struct nvif_notify_conn_rep_v0 {
|
||||
/* nvif_notify_rep ... */
|
||||
__u8 version;
|
||||
__u8 mask;
|
||||
__u8 pad02[6];
|
||||
};
|
||||
|
||||
struct nvif_notify_uevent_req {
|
||||
/* nvif_notify_req ... */
|
||||
};
|
||||
|
@ -10,6 +10,17 @@ union nvif_conn_args {
|
||||
} v0;
|
||||
};
|
||||
|
||||
union nvif_conn_event_args {
|
||||
struct nvif_conn_event_v0 {
|
||||
__u8 version;
|
||||
#define NVIF_CONN_EVENT_V0_PLUG 0x01
|
||||
#define NVIF_CONN_EVENT_V0_UNPLUG 0x02
|
||||
#define NVIF_CONN_EVENT_V0_IRQ 0x04
|
||||
__u8 types;
|
||||
__u8 pad02[6];
|
||||
} v0;
|
||||
};
|
||||
|
||||
#define NVIF_CONN_V0_HPD_STATUS 0x00000000
|
||||
|
||||
union nvif_conn_hpd_status_args {
|
||||
|
@ -8,9 +8,6 @@
|
||||
#include <subdev/bios/gpio.h>
|
||||
|
||||
struct nvkm_gpio_ntfy_req {
|
||||
#define NVKM_GPIO_HI 0x01
|
||||
#define NVKM_GPIO_LO 0x02
|
||||
#define NVKM_GPIO_TOGGLED 0x03
|
||||
u8 mask;
|
||||
u8 line;
|
||||
};
|
||||
@ -23,6 +20,9 @@ struct nvkm_gpio {
|
||||
const struct nvkm_gpio_func *func;
|
||||
struct nvkm_subdev subdev;
|
||||
|
||||
#define NVKM_GPIO_HI BIT(0)
|
||||
#define NVKM_GPIO_LO BIT(1)
|
||||
#define NVKM_GPIO_TOGGLED (NVKM_GPIO_HI | NVKM_GPIO_LO)
|
||||
struct nvkm_event event;
|
||||
};
|
||||
|
||||
|
@ -7,20 +7,6 @@
|
||||
#include <subdev/bios.h>
|
||||
#include <subdev/bios/i2c.h>
|
||||
|
||||
struct nvkm_i2c_ntfy_req {
|
||||
#define NVKM_I2C_PLUG 0x01
|
||||
#define NVKM_I2C_UNPLUG 0x02
|
||||
#define NVKM_I2C_IRQ 0x04
|
||||
#define NVKM_I2C_DONE 0x08
|
||||
#define NVKM_I2C_ANY 0x0f
|
||||
u8 mask;
|
||||
u8 port;
|
||||
};
|
||||
|
||||
struct nvkm_i2c_ntfy_rep {
|
||||
u8 mask;
|
||||
};
|
||||
|
||||
struct nvkm_i2c_bus_probe {
|
||||
struct i2c_board_info dev;
|
||||
u8 udelay; /* set to 0 to use the standard delay */
|
||||
@ -79,6 +65,11 @@ struct nvkm_i2c {
|
||||
struct list_head bus;
|
||||
struct list_head aux;
|
||||
|
||||
#define NVKM_I2C_PLUG BIT(0)
|
||||
#define NVKM_I2C_UNPLUG BIT(1)
|
||||
#define NVKM_I2C_IRQ BIT(2)
|
||||
#define NVKM_I2C_DONE BIT(3)
|
||||
#define NVKM_I2C_ANY (NVKM_I2C_PLUG | NVKM_I2C_UNPLUG | NVKM_I2C_IRQ | NVKM_I2C_DONE)
|
||||
struct nvkm_event event;
|
||||
};
|
||||
|
||||
|
@ -47,8 +47,7 @@
|
||||
#include "nouveau_crtc.h"
|
||||
|
||||
#include <nvif/class.h>
|
||||
#include <nvif/cl0046.h>
|
||||
#include <nvif/event.h>
|
||||
#include <nvif/if0011.h>
|
||||
|
||||
struct drm_display_mode *
|
||||
nouveau_conn_native_mode(struct drm_connector *connector)
|
||||
@ -396,7 +395,8 @@ static void
|
||||
nouveau_connector_destroy(struct drm_connector *connector)
|
||||
{
|
||||
struct nouveau_connector *nv_connector = nouveau_connector(connector);
|
||||
nvif_notify_dtor(&nv_connector->hpd);
|
||||
nvif_event_dtor(&nv_connector->irq);
|
||||
nvif_event_dtor(&nv_connector->hpd);
|
||||
kfree(nv_connector->edid);
|
||||
drm_connector_unregister(connector);
|
||||
drm_connector_cleanup(connector);
|
||||
@ -1178,23 +1178,22 @@ nouveau_connector_hpd(struct nouveau_connector *nv_connector, u64 bits)
|
||||
}
|
||||
|
||||
static int
|
||||
nouveau_connector_hotplug(struct nvif_notify *notify)
|
||||
nouveau_connector_irq(struct nvif_event *event, void *repv, u32 repc)
|
||||
{
|
||||
struct nouveau_connector *nv_connector =
|
||||
container_of(notify, typeof(*nv_connector), hpd);
|
||||
struct drm_connector *connector = &nv_connector->base;
|
||||
struct drm_device *dev = connector->dev;
|
||||
struct nouveau_drm *drm = nouveau_drm(dev);
|
||||
const struct nvif_notify_conn_rep_v0 *rep = notify->data;
|
||||
struct nouveau_connector *nv_connector = container_of(event, typeof(*nv_connector), irq);
|
||||
|
||||
if (rep->mask & NVIF_NOTIFY_CONN_V0_IRQ) {
|
||||
nouveau_dp_irq(drm, nv_connector);
|
||||
return NVIF_NOTIFY_KEEP;
|
||||
}
|
||||
schedule_work(&nv_connector->irq_work);
|
||||
return NVIF_EVENT_KEEP;
|
||||
}
|
||||
|
||||
nouveau_connector_hpd(nv_connector, rep->mask);
|
||||
static int
|
||||
nouveau_connector_hotplug(struct nvif_event *event, void *repv, u32 repc)
|
||||
{
|
||||
struct nouveau_connector *nv_connector = container_of(event, typeof(*nv_connector), hpd);
|
||||
struct nvif_conn_event_v0 *rep = repv;
|
||||
|
||||
return NVIF_NOTIFY_KEEP;
|
||||
nouveau_connector_hpd(nv_connector, rep->types);
|
||||
return NVIF_EVENT_KEEP;
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
@ -1290,6 +1289,7 @@ nouveau_connector_create(struct drm_device *dev,
|
||||
|
||||
connector = &nv_connector->base;
|
||||
nv_connector->index = index;
|
||||
INIT_WORK(&nv_connector->irq_work, nouveau_dp_irq);
|
||||
|
||||
/* attempt to parse vbios connector type and hotplug gpio */
|
||||
nv_connector->dcb = olddcb_conn(dev, index);
|
||||
@ -1401,6 +1401,7 @@ nouveau_connector_create(struct drm_device *dev,
|
||||
|
||||
drm_connector_init(dev, connector, funcs, type);
|
||||
drm_connector_helper_add(connector, &nouveau_connector_helper_funcs);
|
||||
connector->polled = DRM_CONNECTOR_POLL_CONNECT;
|
||||
|
||||
if (nv_connector->dcb && (disp->disp.conn_mask & BIT(nv_connector->index))) {
|
||||
ret = nvif_conn_ctor(&disp->disp, nv_connector->base.name, nv_connector->index,
|
||||
@ -1409,6 +1410,25 @@ nouveau_connector_create(struct drm_device *dev,
|
||||
kfree(nv_connector);
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
|
||||
ret = nvif_conn_event_ctor(&nv_connector->conn, "kmsHotplug",
|
||||
nouveau_connector_hotplug,
|
||||
NVIF_CONN_EVENT_V0_PLUG | NVIF_CONN_EVENT_V0_UNPLUG,
|
||||
&nv_connector->hpd);
|
||||
if (ret == 0)
|
||||
connector->polled = DRM_CONNECTOR_POLL_HPD;
|
||||
|
||||
if (nv_connector->aux.transfer) {
|
||||
ret = nvif_conn_event_ctor(&nv_connector->conn, "kmsDpIrq",
|
||||
nouveau_connector_irq, NVIF_CONN_EVENT_V0_IRQ,
|
||||
&nv_connector->irq);
|
||||
if (ret) {
|
||||
nvif_event_dtor(&nv_connector->hpd);
|
||||
nvif_conn_dtor(&nv_connector->conn);
|
||||
kfree(nv_connector);
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
connector->funcs->reset(connector);
|
||||
@ -1452,21 +1472,6 @@ nouveau_connector_create(struct drm_device *dev,
|
||||
break;
|
||||
}
|
||||
|
||||
ret = nvif_notify_ctor(&disp->disp.object, "kmsHotplug",
|
||||
nouveau_connector_hotplug,
|
||||
true, NV04_DISP_NTFY_CONN,
|
||||
&(struct nvif_notify_conn_req_v0) {
|
||||
.mask = NVIF_NOTIFY_CONN_V0_ANY,
|
||||
.conn = index,
|
||||
},
|
||||
sizeof(struct nvif_notify_conn_req_v0),
|
||||
sizeof(struct nvif_notify_conn_rep_v0),
|
||||
&nv_connector->hpd);
|
||||
if (ret)
|
||||
connector->polled = DRM_CONNECTOR_POLL_CONNECT;
|
||||
else
|
||||
connector->polled = DRM_CONNECTOR_POLL_HPD;
|
||||
|
||||
drm_connector_register(connector);
|
||||
return connector;
|
||||
}
|
||||
|
@ -27,7 +27,7 @@
|
||||
#ifndef __NOUVEAU_CONNECTOR_H__
|
||||
#define __NOUVEAU_CONNECTOR_H__
|
||||
#include <nvif/conn.h>
|
||||
#include <nvif/notify.h>
|
||||
#include <nvif/event.h>
|
||||
|
||||
#include <nvhw/class/cl507d.h>
|
||||
#include <nvhw/class/cl907d.h>
|
||||
@ -125,7 +125,9 @@ struct nouveau_connector {
|
||||
|
||||
struct nvif_conn conn;
|
||||
u64 hpd_pending;
|
||||
struct nvif_notify hpd;
|
||||
struct nvif_event hpd;
|
||||
struct nvif_event irq;
|
||||
struct work_struct irq_work;
|
||||
|
||||
struct drm_dp_aux aux;
|
||||
|
||||
|
@ -42,8 +42,8 @@
|
||||
#include "nv50_display.h"
|
||||
|
||||
#include <nvif/class.h>
|
||||
#include <nvif/if0011.h>
|
||||
#include <nvif/if0013.h>
|
||||
#include <nvif/event.h>
|
||||
#include <dispnv50/crc.h>
|
||||
|
||||
int
|
||||
@ -497,11 +497,11 @@ nouveau_display_hpd_work(struct work_struct *work)
|
||||
|
||||
drm_dbg_kms(dev, "[CONNECTOR:%d:%s] plug:%d unplug:%d irq:%d\n",
|
||||
connector->base.id, connector->name,
|
||||
!!(bits & NVIF_NOTIFY_CONN_V0_PLUG),
|
||||
!!(bits & NVIF_NOTIFY_CONN_V0_UNPLUG),
|
||||
!!(bits & NVIF_NOTIFY_CONN_V0_IRQ));
|
||||
!!(bits & NVIF_CONN_EVENT_V0_PLUG),
|
||||
!!(bits & NVIF_CONN_EVENT_V0_UNPLUG),
|
||||
!!(bits & NVIF_CONN_EVENT_V0_IRQ));
|
||||
|
||||
if (bits & NVIF_NOTIFY_CONN_V0_IRQ) {
|
||||
if (bits & NVIF_CONN_EVENT_V0_IRQ) {
|
||||
if (nouveau_dp_link_check(nv_connector))
|
||||
continue;
|
||||
}
|
||||
@ -584,7 +584,8 @@ nouveau_display_init(struct drm_device *dev, bool resume, bool runtime)
|
||||
drm_connector_list_iter_begin(dev, &conn_iter);
|
||||
nouveau_for_each_non_mst_connector_iter(connector, &conn_iter) {
|
||||
struct nouveau_connector *conn = nouveau_connector(connector);
|
||||
nvif_notify_get(&conn->hpd);
|
||||
nvif_event_allow(&conn->hpd);
|
||||
nvif_event_allow(&conn->irq);
|
||||
}
|
||||
drm_connector_list_iter_end(&conn_iter);
|
||||
|
||||
@ -619,7 +620,8 @@ nouveau_display_fini(struct drm_device *dev, bool suspend, bool runtime)
|
||||
drm_connector_list_iter_begin(dev, &conn_iter);
|
||||
nouveau_for_each_non_mst_connector_iter(connector, &conn_iter) {
|
||||
struct nouveau_connector *conn = nouveau_connector(connector);
|
||||
nvif_notify_put(&conn->hpd);
|
||||
nvif_event_block(&conn->irq);
|
||||
nvif_event_block(&conn->hpd);
|
||||
}
|
||||
drm_connector_list_iter_end(&conn_iter);
|
||||
|
||||
|
@ -29,7 +29,7 @@
|
||||
#include "nouveau_encoder.h"
|
||||
#include "nouveau_crtc.h"
|
||||
|
||||
#include <nvif/event.h>
|
||||
#include <nvif/if0011.h>
|
||||
|
||||
MODULE_PARM_DESC(mst, "Enable DisplayPort multi-stream (default: enabled)");
|
||||
static int nouveau_mst = 1;
|
||||
@ -222,11 +222,14 @@ nouveau_dp_link_check(struct nouveau_connector *nv_connector)
|
||||
return nvif_outp_dp_retrain(&nv_encoder->outp) == 0;
|
||||
}
|
||||
|
||||
void nouveau_dp_irq(struct nouveau_drm *drm,
|
||||
struct nouveau_connector *nv_connector)
|
||||
void
|
||||
nouveau_dp_irq(struct work_struct *work)
|
||||
{
|
||||
struct nouveau_connector *nv_connector =
|
||||
container_of(work, typeof(*nv_connector), irq_work);
|
||||
struct drm_connector *connector = &nv_connector->base;
|
||||
struct nouveau_encoder *outp = find_encoder(connector, DCB_OUTPUT_DP);
|
||||
struct nouveau_drm *drm = nouveau_drm(outp->base.base.dev);
|
||||
struct nv50_mstm *mstm;
|
||||
u64 hpd = 0;
|
||||
int ret;
|
||||
@ -241,14 +244,14 @@ void nouveau_dp_irq(struct nouveau_drm *drm,
|
||||
|
||||
if (mstm && mstm->is_mst) {
|
||||
if (!nv50_mstm_service(drm, nv_connector, mstm))
|
||||
hpd |= NVIF_NOTIFY_CONN_V0_UNPLUG;
|
||||
hpd |= NVIF_CONN_EVENT_V0_UNPLUG;
|
||||
} else {
|
||||
drm_dp_cec_irq(&nv_connector->aux);
|
||||
|
||||
if (nouveau_dp_has_sink_count(connector, outp)) {
|
||||
ret = drm_dp_read_sink_count(&nv_connector->aux);
|
||||
if (ret != outp->dp.sink_count)
|
||||
hpd |= NVIF_NOTIFY_CONN_V0_PLUG;
|
||||
hpd |= NVIF_CONN_EVENT_V0_PLUG;
|
||||
if (ret >= 0)
|
||||
outp->dp.sink_count = ret;
|
||||
}
|
||||
@ -256,7 +259,7 @@ void nouveau_dp_irq(struct nouveau_drm *drm,
|
||||
|
||||
mutex_unlock(&outp->dp.hpd_irq_lock);
|
||||
|
||||
nouveau_connector_hpd(nv_connector, NVIF_NOTIFY_CONN_V0_IRQ | hpd);
|
||||
nouveau_connector_hpd(nv_connector, NVIF_CONN_EVENT_V0_IRQ | hpd);
|
||||
}
|
||||
|
||||
/* TODO:
|
||||
|
@ -142,8 +142,7 @@ enum nouveau_dp_status {
|
||||
|
||||
int nouveau_dp_detect(struct nouveau_connector *, struct nouveau_encoder *);
|
||||
bool nouveau_dp_link_check(struct nouveau_connector *);
|
||||
void nouveau_dp_irq(struct nouveau_drm *drm,
|
||||
struct nouveau_connector *nv_connector);
|
||||
void nouveau_dp_irq(struct work_struct *);
|
||||
enum drm_mode_status nv50_dp_mode_valid(struct drm_connector *,
|
||||
struct nouveau_encoder *,
|
||||
const struct drm_display_mode *,
|
||||
|
@ -26,6 +26,25 @@
|
||||
#include <nvif/class.h>
|
||||
#include <nvif/if0011.h>
|
||||
|
||||
int
|
||||
nvif_conn_event_ctor(struct nvif_conn *conn, const char *name, nvif_event_func func, u8 types,
|
||||
struct nvif_event *event)
|
||||
{
|
||||
struct {
|
||||
struct nvif_event_v0 base;
|
||||
struct nvif_conn_event_v0 conn;
|
||||
} args;
|
||||
int ret;
|
||||
|
||||
args.conn.version = 0;
|
||||
args.conn.types = types;
|
||||
|
||||
ret = nvif_event_ctor_(&conn->object, name ?: "nvifConnHpd", nvif_conn_id(conn),
|
||||
func, true, &args.base, sizeof(args), false, event);
|
||||
NVIF_DEBUG(&conn->object, "[NEW EVENT:HPD types:%02x]", types);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
nvif_conn_hpd_status(struct nvif_conn *conn)
|
||||
{
|
||||
|
@ -29,7 +29,6 @@
|
||||
#include "outp.h"
|
||||
|
||||
#include <core/client.h>
|
||||
#include <core/notify.h>
|
||||
#include <core/ramht.h>
|
||||
#include <subdev/bios.h>
|
||||
#include <subdev/bios/dcb.h>
|
||||
@ -69,54 +68,6 @@ nvkm_disp_vblank(struct nvkm_disp *disp, int head)
|
||||
nvkm_event_send(&disp->vblank, NVKM_DISP_HEAD_EVENT_VBLANK, head, NULL, 0);
|
||||
}
|
||||
|
||||
static int
|
||||
nvkm_disp_hpd_ctor(struct nvkm_object *object, void *data, u32 size,
|
||||
struct nvkm_notify *notify)
|
||||
{
|
||||
struct nvkm_disp *disp =
|
||||
container_of(notify->event, typeof(*disp), hpd);
|
||||
union {
|
||||
struct nvif_notify_conn_req_v0 v0;
|
||||
} *req = data;
|
||||
struct nvkm_outp *outp;
|
||||
int ret = -ENOSYS;
|
||||
|
||||
if (!(ret = nvif_unpack(ret, &data, &size, req->v0, 0, 0, false))) {
|
||||
notify->size = sizeof(struct nvif_notify_conn_rep_v0);
|
||||
list_for_each_entry(outp, &disp->outps, head) {
|
||||
if (ret = -ENXIO, outp->conn->index == req->v0.conn) {
|
||||
if (ret = -ENODEV, outp->conn->hpd.event) {
|
||||
notify->types = req->v0.mask;
|
||||
notify->index = req->v0.conn;
|
||||
ret = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct nvkm_event_func
|
||||
nvkm_disp_hpd_func = {
|
||||
.ctor = nvkm_disp_hpd_ctor
|
||||
};
|
||||
|
||||
int
|
||||
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_CONN:
|
||||
*event = &disp->hpd;
|
||||
return 0;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int
|
||||
nvkm_disp_class_new(struct nvkm_device *device,
|
||||
const struct nvkm_oclass *oclass, void *data, u32 size,
|
||||
@ -325,10 +276,6 @@ nvkm_disp_oneinit(struct nvkm_engine *engine)
|
||||
list_add_tail(&outp->conn->head, &disp->conns);
|
||||
}
|
||||
|
||||
ret = nvkm_event_init(&nvkm_disp_hpd_func, subdev, 3, hpd, &disp->hpd);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (disp->func->oneinit) {
|
||||
ret = disp->func->oneinit(disp);
|
||||
if (ret)
|
||||
@ -376,7 +323,6 @@ nvkm_disp_dtor(struct nvkm_engine *engine)
|
||||
}
|
||||
|
||||
nvkm_event_fini(&disp->vblank);
|
||||
nvkm_event_fini(&disp->hpd);
|
||||
|
||||
while (!list_empty(&disp->conns)) {
|
||||
conn = list_first_entry(&disp->conns, typeof(*conn), head);
|
||||
|
@ -29,38 +29,14 @@
|
||||
|
||||
#include <nvif/event.h>
|
||||
|
||||
static int
|
||||
nvkm_conn_hpd(struct nvkm_notify *notify)
|
||||
{
|
||||
struct nvkm_conn *conn = container_of(notify, typeof(*conn), hpd);
|
||||
struct nvkm_disp *disp = conn->disp;
|
||||
struct nvkm_gpio *gpio = disp->engine.subdev.device->gpio;
|
||||
const struct nvkm_gpio_ntfy_rep *line = notify->data;
|
||||
struct nvif_notify_conn_rep_v0 rep;
|
||||
int index = conn->index;
|
||||
|
||||
CONN_DBG(conn, "HPD: %d", line->mask);
|
||||
|
||||
if (!nvkm_gpio_get(gpio, 0, DCB_GPIO_UNUSED, conn->hpd.index))
|
||||
rep.mask = NVIF_NOTIFY_CONN_V0_UNPLUG;
|
||||
else
|
||||
rep.mask = NVIF_NOTIFY_CONN_V0_PLUG;
|
||||
rep.version = 0;
|
||||
|
||||
nvkm_event_send(&disp->hpd, rep.mask, index, &rep, sizeof(rep));
|
||||
return NVKM_NOTIFY_KEEP;
|
||||
}
|
||||
|
||||
void
|
||||
nvkm_conn_fini(struct nvkm_conn *conn)
|
||||
{
|
||||
nvkm_notify_put(&conn->hpd);
|
||||
}
|
||||
|
||||
void
|
||||
nvkm_conn_init(struct nvkm_conn *conn)
|
||||
{
|
||||
nvkm_notify_get(&conn->hpd);
|
||||
}
|
||||
|
||||
void
|
||||
@ -68,7 +44,6 @@ nvkm_conn_del(struct nvkm_conn **pconn)
|
||||
{
|
||||
struct nvkm_conn *conn = *pconn;
|
||||
if (conn) {
|
||||
nvkm_notify_fini(&conn->hpd);
|
||||
kfree(*pconn);
|
||||
*pconn = NULL;
|
||||
}
|
||||
@ -106,20 +81,6 @@ nvkm_conn_ctor(struct nvkm_disp *disp, int index, struct nvbios_connE *info,
|
||||
}
|
||||
|
||||
conn->info.hpd = func.line;
|
||||
|
||||
ret = nvkm_notify_init(NULL, &gpio->event, nvkm_conn_hpd,
|
||||
true, &(struct nvkm_gpio_ntfy_req) {
|
||||
.mask = NVKM_GPIO_TOGGLED,
|
||||
.line = func.line,
|
||||
},
|
||||
sizeof(struct nvkm_gpio_ntfy_req),
|
||||
sizeof(struct nvkm_gpio_ntfy_rep),
|
||||
&conn->hpd);
|
||||
if (ret) {
|
||||
CONN_ERR(conn, "func %02x failed, %d", info->hpd, ret);
|
||||
} else {
|
||||
CONN_DBG(conn, "func %02x (HPD)", info->hpd);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3,7 +3,6 @@
|
||||
#define __NVKM_DISP_CONN_H__
|
||||
#include "priv.h"
|
||||
|
||||
#include <core/notify.h>
|
||||
#include <subdev/bios.h>
|
||||
#include <subdev/bios/conn.h>
|
||||
|
||||
@ -12,8 +11,6 @@ struct nvkm_conn {
|
||||
int index;
|
||||
struct nvbios_connE info;
|
||||
|
||||
struct nvkm_notify hpd;
|
||||
|
||||
struct list_head head;
|
||||
|
||||
struct nvkm_object object;
|
||||
|
@ -738,31 +738,9 @@ nvkm_dp_enable(struct nvkm_outp *outp, bool auxpwr)
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
nvkm_dp_hpd(struct nvkm_notify *notify)
|
||||
{
|
||||
const struct nvkm_i2c_ntfy_rep *line = notify->data;
|
||||
struct nvkm_outp *outp = container_of(notify, typeof(*outp), dp.hpd);
|
||||
struct nvkm_conn *conn = outp->conn;
|
||||
struct nvkm_disp *disp = outp->disp;
|
||||
struct nvif_notify_conn_rep_v0 rep = {};
|
||||
|
||||
OUTP_DBG(outp, "HPD: %d", line->mask);
|
||||
if (line->mask & NVKM_I2C_IRQ)
|
||||
rep.mask |= NVIF_NOTIFY_CONN_V0_IRQ;
|
||||
if (line->mask & NVKM_I2C_UNPLUG)
|
||||
rep.mask |= NVIF_NOTIFY_CONN_V0_UNPLUG;
|
||||
if (line->mask & NVKM_I2C_PLUG)
|
||||
rep.mask |= NVIF_NOTIFY_CONN_V0_PLUG;
|
||||
|
||||
nvkm_event_send(&disp->hpd, rep.mask, conn->index, &rep, sizeof(rep));
|
||||
return NVKM_NOTIFY_KEEP;
|
||||
}
|
||||
|
||||
static void
|
||||
nvkm_dp_fini(struct nvkm_outp *outp)
|
||||
{
|
||||
nvkm_notify_put(&outp->dp.hpd);
|
||||
nvkm_dp_enable(outp, false);
|
||||
}
|
||||
|
||||
@ -770,14 +748,11 @@ static void
|
||||
nvkm_dp_init(struct nvkm_outp *outp)
|
||||
{
|
||||
nvkm_dp_enable(outp, outp->dp.enabled);
|
||||
nvkm_notify_put(&outp->conn->hpd);
|
||||
nvkm_notify_get(&outp->dp.hpd);
|
||||
}
|
||||
|
||||
static void *
|
||||
nvkm_dp_dtor(struct nvkm_outp *outp)
|
||||
{
|
||||
nvkm_notify_fini(&outp->dp.hpd);
|
||||
return outp;
|
||||
}
|
||||
|
||||
@ -826,21 +801,6 @@ nvkm_dp_new(struct nvkm_disp *disp, int index, struct dcb_output *dcbE, struct n
|
||||
|
||||
OUTP_DBG(outp, "bios dp %02x %02x %02x %02x", outp->dp.version, hdr, cnt, len);
|
||||
|
||||
/* hotplug detect, replaces gpio-based mechanism with aux events */
|
||||
ret = nvkm_notify_init(NULL, &i2c->event, nvkm_dp_hpd, true,
|
||||
&(struct nvkm_i2c_ntfy_req) {
|
||||
.mask = NVKM_I2C_PLUG | NVKM_I2C_UNPLUG |
|
||||
NVKM_I2C_IRQ,
|
||||
.port = outp->dp.aux->id,
|
||||
},
|
||||
sizeof(struct nvkm_i2c_ntfy_req),
|
||||
sizeof(struct nvkm_i2c_ntfy_rep),
|
||||
&outp->dp.hpd);
|
||||
if (ret) {
|
||||
OUTP_ERR(outp, "error monitoring aux hpd: %d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
mutex_init(&outp->dp.mutex);
|
||||
atomic_set(&outp->dp.lt.done, 0);
|
||||
return 0;
|
||||
|
@ -2,7 +2,6 @@
|
||||
#ifndef __NVKM_DISP_OUTP_H__
|
||||
#define __NVKM_DISP_OUTP_H__
|
||||
#include "priv.h"
|
||||
#include <core/notify.h>
|
||||
|
||||
#include <subdev/bios.h>
|
||||
#include <subdev/bios/dcb.h>
|
||||
@ -38,7 +37,6 @@ struct nvkm_outp {
|
||||
|
||||
struct nvkm_i2c_aux *aux;
|
||||
|
||||
struct nvkm_notify hpd;
|
||||
bool enabled;
|
||||
bool aux_pwr;
|
||||
bool aux_pwr_pu;
|
||||
|
@ -42,8 +42,6 @@ struct nvkm_disp_func {
|
||||
} user[];
|
||||
};
|
||||
|
||||
int nvkm_disp_ntfy(struct nvkm_object *, u32, struct nvkm_event **);
|
||||
|
||||
int nv50_disp_oneinit(struct nvkm_disp *);
|
||||
int nv50_disp_init(struct nvkm_disp *);
|
||||
void nv50_disp_fini(struct nvkm_disp *);
|
||||
|
@ -21,11 +21,85 @@
|
||||
*/
|
||||
#define nvkm_uconn(p) container_of((p), struct nvkm_conn, object)
|
||||
#include "conn.h"
|
||||
#include "outp.h"
|
||||
|
||||
#include <core/client.h>
|
||||
#include <core/event.h>
|
||||
#include <subdev/gpio.h>
|
||||
#include <subdev/i2c.h>
|
||||
|
||||
#include <nvif/if0011.h>
|
||||
|
||||
static int
|
||||
nvkm_uconn_uevent_aux(struct nvkm_object *object, u64 token, u32 bits)
|
||||
{
|
||||
union nvif_conn_event_args args;
|
||||
|
||||
args.v0.version = 0;
|
||||
args.v0.types = 0;
|
||||
if (bits & NVKM_I2C_PLUG)
|
||||
args.v0.types |= NVIF_CONN_EVENT_V0_PLUG;
|
||||
if (bits & NVKM_I2C_UNPLUG)
|
||||
args.v0.types |= NVIF_CONN_EVENT_V0_UNPLUG;
|
||||
if (bits & NVKM_I2C_IRQ)
|
||||
args.v0.types |= NVIF_CONN_EVENT_V0_IRQ;
|
||||
|
||||
return object->client->event(token, &args, sizeof(args.v0));
|
||||
}
|
||||
|
||||
static int
|
||||
nvkm_uconn_uevent_gpio(struct nvkm_object *object, u64 token, u32 bits)
|
||||
{
|
||||
union nvif_conn_event_args args;
|
||||
|
||||
args.v0.version = 0;
|
||||
args.v0.types = 0;
|
||||
if (bits & NVKM_GPIO_HI)
|
||||
args.v0.types |= NVIF_CONN_EVENT_V0_PLUG;
|
||||
if (bits & NVKM_GPIO_LO)
|
||||
args.v0.types |= NVIF_CONN_EVENT_V0_UNPLUG;
|
||||
|
||||
return object->client->event(token, &args, sizeof(args.v0));
|
||||
}
|
||||
|
||||
static int
|
||||
nvkm_uconn_uevent(struct nvkm_object *object, void *argv, u32 argc, struct nvkm_uevent *uevent)
|
||||
{
|
||||
struct nvkm_conn *conn = nvkm_uconn(object);
|
||||
struct nvkm_device *device = conn->disp->engine.subdev.device;
|
||||
struct nvkm_outp *outp;
|
||||
union nvif_conn_event_args *args = argv;
|
||||
u64 bits = 0;
|
||||
|
||||
if (!uevent) {
|
||||
if (conn->info.hpd == DCB_GPIO_UNUSED)
|
||||
return -ENOSYS;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (argc != sizeof(args->v0) || args->v0.version != 0)
|
||||
return -ENOSYS;
|
||||
|
||||
list_for_each_entry(outp, &conn->disp->outps, head) {
|
||||
if (outp->info.connector == conn->index && outp->dp.aux) {
|
||||
if (args->v0.types & NVIF_CONN_EVENT_V0_PLUG ) bits |= NVKM_I2C_PLUG;
|
||||
if (args->v0.types & NVIF_CONN_EVENT_V0_UNPLUG) bits |= NVKM_I2C_UNPLUG;
|
||||
if (args->v0.types & NVIF_CONN_EVENT_V0_IRQ ) bits |= NVKM_I2C_IRQ;
|
||||
|
||||
return nvkm_uevent_add(uevent, &device->i2c->event, outp->dp.aux->id, bits,
|
||||
nvkm_uconn_uevent_aux);
|
||||
}
|
||||
}
|
||||
|
||||
if (args->v0.types & NVIF_CONN_EVENT_V0_PLUG ) bits |= NVKM_GPIO_HI;
|
||||
if (args->v0.types & NVIF_CONN_EVENT_V0_UNPLUG) bits |= NVKM_GPIO_LO;
|
||||
if (args->v0.types & NVIF_CONN_EVENT_V0_IRQ)
|
||||
return -EINVAL;
|
||||
|
||||
return nvkm_uevent_add(uevent, &device->gpio->event, conn->info.hpd, bits,
|
||||
nvkm_uconn_uevent_gpio);
|
||||
}
|
||||
|
||||
static int
|
||||
nvkm_uconn_mthd_hpd_status(struct nvkm_conn *conn, void *argv, u32 argc)
|
||||
{
|
||||
@ -82,6 +156,7 @@ static const struct nvkm_object_func
|
||||
nvkm_uconn = {
|
||||
.dtor = nvkm_uconn_dtor,
|
||||
.mthd = nvkm_uconn_mthd,
|
||||
.uevent = nvkm_uconn_uevent,
|
||||
};
|
||||
|
||||
int
|
||||
|
@ -74,7 +74,6 @@ nvkm_udisp_dtor(struct nvkm_object *object)
|
||||
static const struct nvkm_object_func
|
||||
nvkm_udisp = {
|
||||
.dtor = nvkm_udisp_dtor,
|
||||
.ntfy = nvkm_disp_ntfy,
|
||||
.sclass = nvkm_udisp_sclass,
|
||||
};
|
||||
|
||||
|
@ -24,7 +24,6 @@
|
||||
#include "priv.h"
|
||||
|
||||
#include <core/option.h>
|
||||
#include <core/notify.h>
|
||||
|
||||
static int
|
||||
nvkm_gpio_drive(struct nvkm_gpio *gpio, int idx, int line, int dir, int out)
|
||||
@ -123,23 +122,8 @@ nvkm_gpio_intr_init(struct nvkm_event *event, int type, int index)
|
||||
gpio->func->intr_mask(gpio, type, 1 << index, 1 << index);
|
||||
}
|
||||
|
||||
static int
|
||||
nvkm_gpio_intr_ctor(struct nvkm_object *object, void *data, u32 size,
|
||||
struct nvkm_notify *notify)
|
||||
{
|
||||
struct nvkm_gpio_ntfy_req *req = data;
|
||||
if (!WARN_ON(size != sizeof(*req))) {
|
||||
notify->size = sizeof(struct nvkm_gpio_ntfy_rep);
|
||||
notify->types = req->mask;
|
||||
notify->index = req->line;
|
||||
return 0;
|
||||
}
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static const struct nvkm_event_func
|
||||
nvkm_gpio_intr_func = {
|
||||
.ctor = nvkm_gpio_intr_ctor,
|
||||
.init = nvkm_gpio_intr_init,
|
||||
.fini = nvkm_gpio_intr_fini,
|
||||
};
|
||||
@ -153,11 +137,9 @@ nvkm_gpio_intr(struct nvkm_subdev *subdev)
|
||||
gpio->func->intr_stat(gpio, &hi, &lo);
|
||||
|
||||
for (i = 0; (hi | lo) && i < gpio->func->lines; i++) {
|
||||
struct nvkm_gpio_ntfy_rep rep = {
|
||||
.mask = (NVKM_GPIO_HI * !!(hi & (1 << i))) |
|
||||
(NVKM_GPIO_LO * !!(lo & (1 << i))),
|
||||
};
|
||||
nvkm_event_send(&gpio->event, rep.mask, i, &rep, sizeof(rep));
|
||||
u32 mask = (NVKM_GPIO_HI * !!(hi & (1 << i))) |
|
||||
(NVKM_GPIO_LO * !!(lo & (1 << i)));
|
||||
nvkm_event_send(&gpio->event, mask, i, NULL, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -26,7 +26,6 @@
|
||||
#include "bus.h"
|
||||
#include "pad.h"
|
||||
|
||||
#include <core/notify.h>
|
||||
#include <core/option.h>
|
||||
#include <subdev/bios.h>
|
||||
#include <subdev/bios/dcb.h>
|
||||
@ -104,23 +103,8 @@ nvkm_i2c_intr_init(struct nvkm_event *event, int type, int id)
|
||||
i2c->func->aux_mask(i2c, type, aux->intr, aux->intr);
|
||||
}
|
||||
|
||||
static int
|
||||
nvkm_i2c_intr_ctor(struct nvkm_object *object, void *data, u32 size,
|
||||
struct nvkm_notify *notify)
|
||||
{
|
||||
struct nvkm_i2c_ntfy_req *req = data;
|
||||
if (!WARN_ON(size != sizeof(*req))) {
|
||||
notify->size = sizeof(struct nvkm_i2c_ntfy_rep);
|
||||
notify->types = req->mask;
|
||||
notify->index = req->port;
|
||||
return 0;
|
||||
}
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static const struct nvkm_event_func
|
||||
nvkm_i2c_intr_func = {
|
||||
.ctor = nvkm_i2c_intr_ctor,
|
||||
.init = nvkm_i2c_intr_init,
|
||||
.fini = nvkm_i2c_intr_fini,
|
||||
};
|
||||
@ -145,13 +129,8 @@ nvkm_i2c_intr(struct nvkm_subdev *subdev)
|
||||
if (lo & aux->intr) mask |= NVKM_I2C_UNPLUG;
|
||||
if (rq & aux->intr) mask |= NVKM_I2C_IRQ;
|
||||
if (tx & aux->intr) mask |= NVKM_I2C_DONE;
|
||||
if (mask) {
|
||||
struct nvkm_i2c_ntfy_rep rep = {
|
||||
.mask = mask,
|
||||
};
|
||||
nvkm_event_send(&i2c->event, rep.mask, aux->id,
|
||||
&rep, sizeof(rep));
|
||||
}
|
||||
if (mask)
|
||||
nvkm_event_send(&i2c->event, mask, aux->id, NULL, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user