diff options
Diffstat (limited to 'drivers/gpu/drm/nouveau/nvkm/engine/disp')
-rw-r--r-- | drivers/gpu/drm/nouveau/nvkm/engine/disp/conn.c | 6 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nvkm/engine/disp/uconn.c | 43 |
2 files changed, 47 insertions, 2 deletions
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/conn.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/conn.c index febc5c274488..7ed11801a3ae 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/conn.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/conn.c @@ -86,6 +86,7 @@ nvkm_conn_ctor(struct nvkm_disp *disp, int index, struct nvbios_connE *info, conn->disp = disp; conn->index = index; conn->info = *info; + conn->info.hpd = DCB_GPIO_UNUSED; CONN_DBG(conn, "type %02x loc %d hpd %02x dp %x di %x sr %x lcdid %x", info->type, info->location, info->hpd, info->dp, @@ -100,11 +101,12 @@ nvkm_conn_ctor(struct nvkm_disp *disp, int index, struct nvbios_connE *info, ret = nvkm_gpio_find(gpio, 0, info->hpd, DCB_GPIO_UNUSED, &func); if (ret) { - CONN_ERR(conn, "func %02x lookup failed, %d", - info->hpd, ret); + CONN_ERR(conn, "func %02x lookup failed, %d", info->hpd, ret); return; } + 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, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/uconn.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/uconn.c index 3fbbb6e6a66b..fd9f18144c26 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/uconn.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/uconn.c @@ -22,8 +22,50 @@ #define nvkm_uconn(p) container_of((p), struct nvkm_conn, object) #include "conn.h" +#include <subdev/gpio.h> + #include <nvif/if0011.h> +static int +nvkm_uconn_mthd_hpd_status(struct nvkm_conn *conn, void *argv, u32 argc) +{ + struct nvkm_gpio *gpio = conn->disp->engine.subdev.device->gpio; + union nvif_conn_hpd_status_args *args = argv; + + if (argc != sizeof(args->v0) || args->v0.version != 0) + return -ENOSYS; + + args->v0.support = gpio && conn->info.hpd != DCB_GPIO_UNUSED; + args->v0.present = 0; + + if (args->v0.support) { + int ret = nvkm_gpio_get(gpio, 0, DCB_GPIO_UNUSED, conn->info.hpd); + + if (WARN_ON(ret < 0)) { + args->v0.support = false; + return 0; + } + + args->v0.present = ret; + } + + return 0; +} + +static int +nvkm_uconn_mthd(struct nvkm_object *object, u32 mthd, void *argv, u32 argc) +{ + struct nvkm_conn *conn = nvkm_uconn(object); + + switch (mthd) { + case NVIF_CONN_V0_HPD_STATUS: return nvkm_uconn_mthd_hpd_status(conn, argv, argc); + default: + break; + } + + return -EINVAL; +} + static void * nvkm_uconn_dtor(struct nvkm_object *object) { @@ -39,6 +81,7 @@ nvkm_uconn_dtor(struct nvkm_object *object) static const struct nvkm_object_func nvkm_uconn = { .dtor = nvkm_uconn_dtor, + .mthd = nvkm_uconn_mthd, }; int |