Commit 773eb04d authored by Ben Skeggs's avatar Ben Skeggs

drm/nouveau/disp: expose conn event class

This removes some now-unnecessary nesting of workqueues.

v2:
- use ?: (lyude)
Signed-off-by: default avatarBen Skeggs <bskeggs@redhat.com>
Reviewed-by: default avatarLyude Paul <lyude@redhat.com>
parent ffd26641
......@@ -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);
}
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment