From bd7a61bcbb50bfca1b9a585f17d5590dbb521b78 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Tue, 19 Sep 2023 17:56:22 -0400 Subject: drm/nouveau/disp: add dp aux xfer method - preparation for GSP-RM Signed-off-by: Ben Skeggs Reviewed-by: Lyude Paul Acked-by: Danilo Krummrich Signed-off-by: Lyude Paul Link: https://patchwork.freedesktop.org/patch/msgid/20230919220442.202488-28-lyude@redhat.com --- drivers/gpu/drm/nouveau/dispnv50/disp.c | 32 +++++++++++------------- drivers/gpu/drm/nouveau/include/nvif/if0012.h | 12 +++++++++ drivers/gpu/drm/nouveau/include/nvif/outp.h | 2 ++ drivers/gpu/drm/nouveau/nouveau_connector.c | 12 +++------ drivers/gpu/drm/nouveau/nouveau_encoder.h | 1 - drivers/gpu/drm/nouveau/nvif/outp.c | 24 ++++++++++++++++++ drivers/gpu/drm/nouveau/nvkm/engine/disp/dp.c | 14 +++++++++++ drivers/gpu/drm/nouveau/nvkm/engine/disp/outp.h | 1 + drivers/gpu/drm/nouveau/nvkm/engine/disp/uoutp.c | 27 +++++++++++++++++--- 9 files changed, 94 insertions(+), 31 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.c b/drivers/gpu/drm/nouveau/dispnv50/disp.c index 11b11284a321..ee53bc5d1004 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/disp.c +++ b/drivers/gpu/drm/nouveau/dispnv50/disp.c @@ -1704,14 +1704,13 @@ 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->dcb->type == DCB_OUTPUT_DP) mutex_destroy(&nv_encoder->dp.hpd_irq_lock); + nvif_outp_dtor(&nv_encoder->outp); kfree(encoder); } @@ -1764,22 +1763,22 @@ nv50_sor_create(struct nouveau_encoder *nv_encoder) nv50_outp_dump_caps(drm, nv_encoder); if (dcbe->type == DCB_OUTPUT_DP) { - struct nvkm_i2c_aux *aux = - nvkm_i2c_aux_find(i2c, dcbe->i2c_index); - mutex_init(&nv_encoder->dp.hpd_irq_lock); - if (aux) { - 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 = &aux->i2c; - } else { - nv_encoder->i2c = &nv_connector->aux.ddc; - } - nv_encoder->aux = aux; + 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. + */ + struct nvkm_i2c_aux *aux; + + aux = nvkm_i2c_aux_find(i2c, dcbe->i2c_index); + if (!aux) + return -EINVAL; + + nv_encoder->i2c = &aux->i2c; + } else { + nv_encoder->i2c = &nv_connector->aux.ddc; } if (nv_connector->type != DCB_CONNECTOR_eDP && @@ -1925,7 +1924,6 @@ nv50_pior_create(struct nouveau_encoder *nv_encoder) } nv_encoder->i2c = ddc; - nv_encoder->aux = aux; encoder = to_drm_encoder(nv_encoder); drm_encoder_init(connector->dev, encoder, &nv50_pior_func, type, diff --git a/drivers/gpu/drm/nouveau/include/nvif/if0012.h b/drivers/gpu/drm/nouveau/include/nvif/if0012.h index ee4cec541a90..94f1e55b0ce6 100644 --- a/drivers/gpu/drm/nouveau/include/nvif/if0012.h +++ b/drivers/gpu/drm/nouveau/include/nvif/if0012.h @@ -32,6 +32,7 @@ union nvif_outp_args { #define NVIF_OUTP_V0_HDA_ELD 0x61 #define NVIF_OUTP_V0_DP_AUX_PWR 0x70 +#define NVIF_OUTP_V0_DP_AUX_XFER 0x71 #define NVIF_OUTP_V0_DP_RETRAIN 0x73 #define NVIF_OUTP_V0_DP_MST_VCPI 0x78 @@ -182,6 +183,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 0ddaec9416ee..dd4dd0e2a7a1 100644 --- a/drivers/gpu/drm/nouveau/include/nvif/outp.h +++ b/drivers/gpu/drm/nouveau/include/nvif/outp.h @@ -56,7 +56,9 @@ int nvif_outp_hdmi(struct nvif_outp *, int head, bool enable, u8 max_ac_packet, 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_pwr(struct nvif_outp *, bool enable); +int nvif_outp_dp_aux_xfer(struct nvif_outp *, u8 type, u8 *size, u32 addr, u8 *data); int nvif_outp_dp_retrain(struct nvif_outp *); int nvif_outp_dp_mst_vcpi(struct nvif_outp *, int head, u8 start_slot, u8 num_slots, u16 pbn, u16 aligned_pbn); diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c index c079686fa240..063cefe26be2 100644 --- a/drivers/gpu/drm/nouveau/nouveau_connector.c +++ b/drivers/gpu/drm/nouveau/nouveau_connector.c @@ -1226,23 +1226,17 @@ nouveau_connector_aux_xfer(struct drm_dp_aux *obj, struct drm_dp_aux_msg *msg) struct nouveau_connector *nv_connector = container_of(obj, typeof(*nv_connector), aux); struct nouveau_encoder *nv_encoder; - struct nvkm_i2c_aux *aux; u8 size = msg->size; int ret; nv_encoder = find_encoder(&nv_connector->base, DCB_OUTPUT_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 b3a9415ba879..aacdf2814aba 100644 --- a/drivers/gpu/drm/nouveau/nouveau_encoder.h +++ b/drivers/gpu/drm/nouveau/nouveau_encoder.h @@ -52,7 +52,6 @@ struct nouveau_encoder { struct nouveau_connector *conn; 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 dbb0986f0555..df6e89379982 100644 --- a/drivers/gpu/drm/nouveau/nvif/outp.c +++ b/drivers/gpu/drm/nouveau/nvif/outp.c @@ -76,6 +76,30 @@ nvif_outp_acquire_dp(struct nvif_outp *outp, u8 dpcd[DP_RECEIVER_CAP_SIZE], return ret; } +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_DEBUG(&outp->object, "[DP_AUX_XFER type:%d size:%d addr:%05x] %d size:%d (ret: %d)", + args.type, size, args.addr, ret, args.size, ret); + if (ret < 0) + return ret; + + *psize = args.size; + + memcpy(data, args.data, size); + return ret; +} + int nvif_outp_dp_aux_pwr(struct nvif_outp *outp, bool enable) { diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/dp.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/dp.c index 99fe7ef07a44..49fbb32f5022 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/dp.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/dp.c @@ -41,6 +41,19 @@ */ #define AMPERE_IED_HACK(disp) ((disp)->engine.subdev.device->card_type >= GA100) +static int +nvkm_dp_aux_xfer(struct nvkm_outp *outp, u8 type, u32 addr, u8 *data, u8 *size) +{ + int ret = nvkm_i2c_aux_acquire(outp->dp.aux); + + if (ret) + return ret; + + ret = nvkm_i2c_aux_xfer(outp->dp.aux, false, type, addr, data, size); + nvkm_i2c_aux_release(outp->dp.aux); + return ret; +} + static int nvkm_dp_aux_pwr(struct nvkm_outp *outp, bool pu) { @@ -823,6 +836,7 @@ nvkm_dp_func = { .bl.get = nvkm_outp_bl_get, .bl.set = nvkm_outp_bl_set, .dp.aux_pwr = nvkm_dp_aux_pwr, + .dp.aux_xfer = nvkm_dp_aux_xfer, }; int diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/outp.h b/drivers/gpu/drm/nouveau/nvkm/engine/disp/outp.h index 513794a278a9..a2391b224ea4 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/outp.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/outp.h @@ -107,6 +107,7 @@ struct nvkm_outp_func { struct { int (*aux_pwr)(struct nvkm_outp *, bool pu); + int (*aux_xfer)(struct nvkm_outp *, u8 type, u32 addr, u8 *data, u8 *size); } dp; }; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/uoutp.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/uoutp.c index 6ca364e953bd..cd92db9028a3 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/uoutp.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/uoutp.c @@ -25,6 +25,8 @@ #include "head.h" #include "ior.h" +#include + #include static int @@ -68,6 +70,20 @@ nvkm_uoutp_mthd_acquire_dp(struct nvkm_outp *outp, u8 dpcd[DP_RECEIVER_CAP_SIZE] return 0; } +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; + + if (argc != sizeof(args->v0) || args->v0.version != 0) + return -ENOSYS; + if (!outp->func->dp.aux_xfer) + return -EINVAL; + + return outp->func->dp.aux_xfer(outp, args->v0.type, args->v0.addr, + args->v0.data, &args->v0.size); +} + static int nvkm_uoutp_mthd_dp_aux_pwr(struct nvkm_outp *outp, void *argv, u32 argc) { @@ -429,7 +445,7 @@ 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); @@ -440,11 +456,13 @@ nvkm_uoutp_mthd_noacquire(struct nvkm_outp *outp, u32 mthd, void *argv, u32 argc case NVIF_OUTP_V0_BL_GET : return nvkm_uoutp_mthd_bl_get (outp, argv, argc); case NVIF_OUTP_V0_BL_SET : return nvkm_uoutp_mthd_bl_set (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 @@ -452,12 +470,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) -- cgit v1.2.3