summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBen Skeggs <bskeggs@redhat.com>2022-10-13 08:04:19 +1000
committerBen Skeggs <bskeggs@redhat.com>2022-10-13 08:04:19 +1000
commitbeea5ab213b28f7abf7c3405439ac9abcd1b8415 (patch)
tree75b1ca1d1b4eae6bcb0733e3cf2e0b9fb1b20bd0
parent7e8cd96792903aae8fd5844682f6150e9edf97da (diff)
drm/nouveau/disp: add output aux xfer method
- preparation for GSP-RM. Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
-rw-r--r--drivers/gpu/drm/nouveau/dispnv50/disp.c17
-rw-r--r--drivers/gpu/drm/nouveau/include/nvif/if0012.h12
-rw-r--r--drivers/gpu/drm/nouveau/include/nvif/outp.h1
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_connector.c11
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_encoder.h1
-rw-r--r--drivers/gpu/drm/nouveau/nvif/outp.c24
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/uoutp.c33
7 files changed, 78 insertions, 21 deletions
diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.c b/drivers/gpu/drm/nouveau/dispnv50/disp.c
index e8788e58c09c..53b969b5c62a 100644
--- a/drivers/gpu/drm/nouveau/dispnv50/disp.c
+++ b/drivers/gpu/drm/nouveau/dispnv50/disp.c
@@ -1646,14 +1646,14 @@ nv50_sor_destroy(struct drm_encoder *encoder)
{
struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
- nvif_outp_dtor(&nv_encoder->outp);
-
nv50_mstm_del(&nv_encoder->dp.mstm);
drm_encoder_cleanup(encoder);
if (nv_encoder->outp.info.proto == NVIF_OUTP_DP)
mutex_destroy(&nv_encoder->dp.hpd_irq_lock);
+ nvif_outp_dtor(&nv_encoder->outp);
+
kfree(encoder);
}
@@ -1715,16 +1715,18 @@ nv50_sor_create(struct drm_connector *connector, struct nouveau_encoder *nv_enco
if (nv_encoder->outp.info.proto == NVIF_OUTP_DP) {
mutex_init(&nv_encoder->dp.hpd_irq_lock);
- nv_encoder->aux = nvkm_i2c_aux_find(i2c, nv_encoder->outp.info.dp.aux);
- if (!nv_encoder->aux)
- return -EINVAL;
-
if (disp->disp->object.oclass < GF110_DISP) {
/* HW has no support for address-only
* transactions, so we're required to
* use custom I2C-over-AUX code.
*/
- nv_encoder->i2c = &nv_encoder->aux->i2c;
+ struct nvkm_i2c_aux *aux;
+
+ aux = nvkm_i2c_aux_find(i2c, nv_encoder->outp.info.dp.aux);
+ if (!aux)
+ return -EINVAL;
+
+ nv_encoder->i2c = &aux->i2c;
} else {
nv_encoder->i2c = &nv_connector->aux.ddc;
}
@@ -1868,7 +1870,6 @@ nv50_pior_create(struct drm_connector *connector, struct nouveau_encoder *outp)
}
outp->i2c = ddc;
- outp->aux = aux;
encoder = to_drm_encoder(outp);
encoder->possible_crtcs = outp->outp.info.heads;
diff --git a/drivers/gpu/drm/nouveau/include/nvif/if0012.h b/drivers/gpu/drm/nouveau/include/nvif/if0012.h
index 957889bd6d3c..e55c7f3818f2 100644
--- a/drivers/gpu/drm/nouveau/include/nvif/if0012.h
+++ b/drivers/gpu/drm/nouveau/include/nvif/if0012.h
@@ -51,6 +51,7 @@ union nvif_outp_args {
#define NVIF_OUTP_V0_BL_SET 0x43
#define NVIF_OUTP_V0_DP_AUX_PWR 0x50
+#define NVIF_OUTP_V0_DP_AUX_XFER 0x51
#define NVIF_OUTP_V0_DP_RETRAIN 0x52
#define NVIF_OUTP_V0_DP_MST_VCPI 0x56
@@ -162,6 +163,17 @@ union nvif_outp_dp_aux_pwr_args {
} v0;
};
+union nvif_outp_dp_aux_xfer_args {
+ struct nvif_outp_dp_aux_xfer_v0 {
+ __u8 version;
+ __u8 pad01;
+ __u8 type;
+ __u8 size;
+ __u32 addr;
+ __u8 data[16];
+ } v0;
+};
+
union nvif_outp_dp_retrain_args {
struct nvif_outp_dp_retrain_vn {
} vn;
diff --git a/drivers/gpu/drm/nouveau/include/nvif/outp.h b/drivers/gpu/drm/nouveau/include/nvif/outp.h
index dc79b6398832..dc7be7d8d8da 100644
--- a/drivers/gpu/drm/nouveau/include/nvif/outp.h
+++ b/drivers/gpu/drm/nouveau/include/nvif/outp.h
@@ -74,6 +74,7 @@ int nvif_outp_acquire_dp(struct nvif_outp *, u8 dpcd[16],
void nvif_outp_release(struct nvif_outp *);
int nvif_outp_infoframe(struct nvif_outp *, u8 type, struct nvif_outp_infoframe_v0 *, u32 size);
int nvif_outp_hda_eld(struct nvif_outp *, int head, void *data, u32 size);
+int nvif_outp_dp_aux_xfer(struct nvif_outp *, u8 type, u8 *size, u32 addr, u8 *data);
int nvif_outp_dp_aux_pwr(struct nvif_outp *, bool enable);
int nvif_outp_dp_retrain(struct nvif_outp *);
int nvif_outp_dp_mst_vcpi(struct nvif_outp *, int head,
diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c
index 6650d1a35722..89a65c559ec9 100644
--- a/drivers/gpu/drm/nouveau/nouveau_connector.c
+++ b/drivers/gpu/drm/nouveau/nouveau_connector.c
@@ -1220,18 +1220,13 @@ nouveau_connector_aux_xfer(struct drm_dp_aux *obj, struct drm_dp_aux_msg *msg)
int ret;
nv_encoder = find_encoder(&nv_connector->base, NVIF_OUTP_DP);
- if (!nv_encoder || !(aux = nv_encoder->aux))
+ if (!nv_encoder)
return -ENODEV;
if (WARN_ON(msg->size > 16))
return -E2BIG;
- ret = nvkm_i2c_aux_acquire(aux);
- if (ret)
- return ret;
-
- ret = nvkm_i2c_aux_xfer(aux, false, msg->request, msg->address,
- msg->buffer, &size);
- nvkm_i2c_aux_release(aux);
+ ret = nvif_outp_dp_aux_xfer(&nv_encoder->outp,
+ msg->request, &size, msg->address, msg->buffer);
if (ret >= 0) {
msg->reply = ret;
return size;
diff --git a/drivers/gpu/drm/nouveau/nouveau_encoder.h b/drivers/gpu/drm/nouveau/nouveau_encoder.h
index 70c1ad6c4d9d..b90c612433c0 100644
--- a/drivers/gpu/drm/nouveau/nouveau_encoder.h
+++ b/drivers/gpu/drm/nouveau/nouveau_encoder.h
@@ -50,7 +50,6 @@ struct nouveau_encoder {
int or;
struct i2c_adapter *i2c;
- struct nvkm_i2c_aux *aux;
/* different to drm_encoder.crtc, this reflects what's
* actually programmed on the hw, not the proposed crtc */
diff --git a/drivers/gpu/drm/nouveau/nvif/outp.c b/drivers/gpu/drm/nouveau/nvif/outp.c
index 0894b4dbfc09..a80c40fb8f5f 100644
--- a/drivers/gpu/drm/nouveau/nvif/outp.c
+++ b/drivers/gpu/drm/nouveau/nvif/outp.c
@@ -96,6 +96,30 @@ nvif_outp_dp_aux_pwr(struct nvif_outp *outp, bool enable)
}
int
+nvif_outp_dp_aux_xfer(struct nvif_outp *outp, u8 type, u8 *psize, u32 addr, u8 *data)
+{
+ struct nvif_outp_dp_aux_xfer_v0 args;
+ u8 size = *psize;
+ int ret;
+
+ args.version = 0;
+ args.type = type;
+ args.size = size;
+ args.addr = addr;
+ memcpy(args.data, data, size);
+ ret = nvif_object_mthd(&outp->object, NVIF_OUTP_V0_DP_AUX_XFER, &args, sizeof(args));
+ NVIF_ERRON(ret < 0, &outp->object, "[DP_AUX_XFER type:%d size:%d addr:%05x] %d size:%d",
+ args.type, size, args.addr, ret, args.size);
+ if (ret < 0)
+ return ret;
+
+ *psize = args.size;
+
+ memcpy(data, args.data, *psize);
+ return ret;
+}
+
+int
nvif_outp_hda_eld(struct nvif_outp *outp, int head, void *data, u32 size)
{
struct {
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/uoutp.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/uoutp.c
index 5dc7e2a8fea6..cdff16cb2db7 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/uoutp.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/uoutp.c
@@ -27,6 +27,7 @@
#include "ior.h"
#include <subdev/gpio.h>
+#include <subdev/i2c.h>
#include <nvif/if0012.h>
@@ -89,6 +90,27 @@ nvkm_uoutp_mthd_dp_retrain(struct nvkm_outp *outp, void *argv, u32 argc)
}
static int
+nvkm_uoutp_mthd_dp_aux_xfer(struct nvkm_outp *outp, void *argv, u32 argc)
+{
+ union nvif_outp_dp_aux_xfer_args *args = argv;
+ int ret;
+
+ if (argc != sizeof(args->v0) || args->v0.version != 0)
+ return -ENOSYS;
+ if (outp->proto != DP)
+ return -EINVAL;
+
+ ret = nvkm_i2c_aux_acquire(outp->dp.aux);
+ if (ret)
+ return ret;
+
+ ret = nvkm_i2c_aux_xfer(outp->dp.aux, false, args->v0.type, args->v0.addr,
+ args->v0.data, &args->v0.size);
+ nvkm_i2c_aux_release(outp->dp.aux);
+ return ret;
+}
+
+static int
nvkm_uoutp_mthd_dp_aux_pwr(struct nvkm_outp *outp, void *argv, u32 argc)
{
union nvif_outp_dp_aux_pwr_args *args = argv;
@@ -359,18 +381,20 @@ nvkm_uoutp_mthd_acquired(struct nvkm_outp *outp, u32 mthd, void *argv, u32 argc)
}
static int
-nvkm_uoutp_mthd_noacquire(struct nvkm_outp *outp, u32 mthd, void *argv, u32 argc)
+nvkm_uoutp_mthd_noacquire(struct nvkm_outp *outp, u32 mthd, void *argv, u32 argc, bool *invalid)
{
switch (mthd) {
case NVIF_OUTP_V0_DETECT : return nvkm_uoutp_mthd_detect (outp, argv, argc);
case NVIF_OUTP_V0_ACQUIRE : return nvkm_uoutp_mthd_acquire (outp, argv, argc);
case NVIF_OUTP_V0_LOAD_DETECT: return nvkm_uoutp_mthd_load_detect(outp, argv, argc);
case NVIF_OUTP_V0_DP_AUX_PWR : return nvkm_uoutp_mthd_dp_aux_pwr (outp, argv, argc);
+ case NVIF_OUTP_V0_DP_AUX_XFER: return nvkm_uoutp_mthd_dp_aux_xfer(outp, argv, argc);
default:
break;
}
- return 1;
+ *invalid = true;
+ return 0;
}
static int
@@ -378,12 +402,13 @@ nvkm_uoutp_mthd(struct nvkm_object *object, u32 mthd, void *argv, u32 argc)
{
struct nvkm_outp *outp = nvkm_uoutp(object);
struct nvkm_disp *disp = outp->disp;
+ bool invalid = false;
int ret;
mutex_lock(&disp->super.mutex);
- ret = nvkm_uoutp_mthd_noacquire(outp, mthd, argv, argc);
- if (ret <= 0)
+ ret = nvkm_uoutp_mthd_noacquire(outp, mthd, argv, argc, &invalid);
+ if (!invalid)
goto done;
if (outp->ior)