diff options
author | Ben Skeggs <bskeggs@redhat.com> | 2022-10-13 08:04:19 +1000 |
---|---|---|
committer | Ben Skeggs <bskeggs@redhat.com> | 2022-10-13 08:04:19 +1000 |
commit | beea5ab213b28f7abf7c3405439ac9abcd1b8415 (patch) | |
tree | 75b1ca1d1b4eae6bcb0733e3cf2e0b9fb1b20bd0 | |
parent | 7e8cd96792903aae8fd5844682f6150e9edf97da (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.c | 17 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/include/nvif/if0012.h | 12 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/include/nvif/outp.h | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_connector.c | 11 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_encoder.h | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nvif/outp.c | 24 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nvkm/engine/disp/uoutp.c | 33 |
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) |