Commit bd7a61bc authored by Ben Skeggs's avatar Ben Skeggs Committed by Lyude Paul

drm/nouveau/disp: add dp aux xfer method

- preparation for GSP-RM
Signed-off-by: default avatarBen Skeggs <bskeggs@redhat.com>
Reviewed-by: default avatarLyude Paul <lyude@redhat.com>
Acked-by: default avatarDanilo Krummrich <me@dakr.org>
Signed-off-by: default avatarLyude Paul <lyude@redhat.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20230919220442.202488-28-lyude@redhat.com
parent 0bd4e9f7
...@@ -1704,14 +1704,13 @@ nv50_sor_destroy(struct drm_encoder *encoder) ...@@ -1704,14 +1704,13 @@ nv50_sor_destroy(struct drm_encoder *encoder)
{ {
struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
nvif_outp_dtor(&nv_encoder->outp);
nv50_mstm_del(&nv_encoder->dp.mstm); nv50_mstm_del(&nv_encoder->dp.mstm);
drm_encoder_cleanup(encoder); drm_encoder_cleanup(encoder);
if (nv_encoder->dcb->type == DCB_OUTPUT_DP) if (nv_encoder->dcb->type == DCB_OUTPUT_DP)
mutex_destroy(&nv_encoder->dp.hpd_irq_lock); mutex_destroy(&nv_encoder->dp.hpd_irq_lock);
nvif_outp_dtor(&nv_encoder->outp);
kfree(encoder); kfree(encoder);
} }
...@@ -1764,23 +1763,23 @@ nv50_sor_create(struct nouveau_encoder *nv_encoder) ...@@ -1764,23 +1763,23 @@ nv50_sor_create(struct nouveau_encoder *nv_encoder)
nv50_outp_dump_caps(drm, nv_encoder); nv50_outp_dump_caps(drm, nv_encoder);
if (dcbe->type == DCB_OUTPUT_DP) { 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); mutex_init(&nv_encoder->dp.hpd_irq_lock);
if (aux) {
if (disp->disp->object.oclass < GF110_DISP) { if (disp->disp->object.oclass < GF110_DISP) {
/* HW has no support for address-only /* HW has no support for address-only
* transactions, so we're required to * transactions, so we're required to
* use custom I2C-over-AUX code. * 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; nv_encoder->i2c = &aux->i2c;
} else { } else {
nv_encoder->i2c = &nv_connector->aux.ddc; nv_encoder->i2c = &nv_connector->aux.ddc;
} }
nv_encoder->aux = aux;
}
if (nv_connector->type != DCB_CONNECTOR_eDP && if (nv_connector->type != DCB_CONNECTOR_eDP &&
nv50_has_mst(drm)) { nv50_has_mst(drm)) {
...@@ -1925,7 +1924,6 @@ nv50_pior_create(struct nouveau_encoder *nv_encoder) ...@@ -1925,7 +1924,6 @@ nv50_pior_create(struct nouveau_encoder *nv_encoder)
} }
nv_encoder->i2c = ddc; nv_encoder->i2c = ddc;
nv_encoder->aux = aux;
encoder = to_drm_encoder(nv_encoder); encoder = to_drm_encoder(nv_encoder);
drm_encoder_init(connector->dev, encoder, &nv50_pior_func, type, drm_encoder_init(connector->dev, encoder, &nv50_pior_func, type,
......
...@@ -32,6 +32,7 @@ union nvif_outp_args { ...@@ -32,6 +32,7 @@ union nvif_outp_args {
#define NVIF_OUTP_V0_HDA_ELD 0x61 #define NVIF_OUTP_V0_HDA_ELD 0x61
#define NVIF_OUTP_V0_DP_AUX_PWR 0x70 #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_RETRAIN 0x73
#define NVIF_OUTP_V0_DP_MST_VCPI 0x78 #define NVIF_OUTP_V0_DP_MST_VCPI 0x78
...@@ -182,6 +183,17 @@ union nvif_outp_dp_aux_pwr_args { ...@@ -182,6 +183,17 @@ union nvif_outp_dp_aux_pwr_args {
} v0; } 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 { union nvif_outp_dp_retrain_args {
struct nvif_outp_dp_retrain_vn { struct nvif_outp_dp_retrain_vn {
} vn; } vn;
......
...@@ -56,7 +56,9 @@ int nvif_outp_hdmi(struct nvif_outp *, int head, bool enable, u8 max_ac_packet, ...@@ -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_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_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_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_retrain(struct nvif_outp *);
int nvif_outp_dp_mst_vcpi(struct nvif_outp *, int head, int nvif_outp_dp_mst_vcpi(struct nvif_outp *, int head,
u8 start_slot, u8 num_slots, u16 pbn, u16 aligned_pbn); u8 start_slot, u8 num_slots, u16 pbn, u16 aligned_pbn);
......
...@@ -1226,23 +1226,17 @@ nouveau_connector_aux_xfer(struct drm_dp_aux *obj, struct drm_dp_aux_msg *msg) ...@@ -1226,23 +1226,17 @@ nouveau_connector_aux_xfer(struct drm_dp_aux *obj, struct drm_dp_aux_msg *msg)
struct nouveau_connector *nv_connector = struct nouveau_connector *nv_connector =
container_of(obj, typeof(*nv_connector), aux); container_of(obj, typeof(*nv_connector), aux);
struct nouveau_encoder *nv_encoder; struct nouveau_encoder *nv_encoder;
struct nvkm_i2c_aux *aux;
u8 size = msg->size; u8 size = msg->size;
int ret; int ret;
nv_encoder = find_encoder(&nv_connector->base, DCB_OUTPUT_DP); nv_encoder = find_encoder(&nv_connector->base, DCB_OUTPUT_DP);
if (!nv_encoder || !(aux = nv_encoder->aux)) if (!nv_encoder)
return -ENODEV; return -ENODEV;
if (WARN_ON(msg->size > 16)) if (WARN_ON(msg->size > 16))
return -E2BIG; return -E2BIG;
ret = nvkm_i2c_aux_acquire(aux); ret = nvif_outp_dp_aux_xfer(&nv_encoder->outp,
if (ret) msg->request, &size, msg->address, msg->buffer);
return ret;
ret = nvkm_i2c_aux_xfer(aux, false, msg->request, msg->address,
msg->buffer, &size);
nvkm_i2c_aux_release(aux);
if (ret >= 0) { if (ret >= 0) {
msg->reply = ret; msg->reply = ret;
return size; return size;
......
...@@ -52,7 +52,6 @@ struct nouveau_encoder { ...@@ -52,7 +52,6 @@ struct nouveau_encoder {
struct nouveau_connector *conn; struct nouveau_connector *conn;
struct i2c_adapter *i2c; struct i2c_adapter *i2c;
struct nvkm_i2c_aux *aux;
/* different to drm_encoder.crtc, this reflects what's /* different to drm_encoder.crtc, this reflects what's
* actually programmed on the hw, not the proposed crtc */ * actually programmed on the hw, not the proposed crtc */
......
...@@ -76,6 +76,30 @@ nvif_outp_acquire_dp(struct nvif_outp *outp, u8 dpcd[DP_RECEIVER_CAP_SIZE], ...@@ -76,6 +76,30 @@ nvif_outp_acquire_dp(struct nvif_outp *outp, u8 dpcd[DP_RECEIVER_CAP_SIZE],
return ret; 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 int
nvif_outp_dp_aux_pwr(struct nvif_outp *outp, bool enable) nvif_outp_dp_aux_pwr(struct nvif_outp *outp, bool enable)
{ {
......
...@@ -41,6 +41,19 @@ ...@@ -41,6 +41,19 @@
*/ */
#define AMPERE_IED_HACK(disp) ((disp)->engine.subdev.device->card_type >= GA100) #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 static int
nvkm_dp_aux_pwr(struct nvkm_outp *outp, bool pu) nvkm_dp_aux_pwr(struct nvkm_outp *outp, bool pu)
{ {
...@@ -823,6 +836,7 @@ nvkm_dp_func = { ...@@ -823,6 +836,7 @@ nvkm_dp_func = {
.bl.get = nvkm_outp_bl_get, .bl.get = nvkm_outp_bl_get,
.bl.set = nvkm_outp_bl_set, .bl.set = nvkm_outp_bl_set,
.dp.aux_pwr = nvkm_dp_aux_pwr, .dp.aux_pwr = nvkm_dp_aux_pwr,
.dp.aux_xfer = nvkm_dp_aux_xfer,
}; };
int int
......
...@@ -107,6 +107,7 @@ struct nvkm_outp_func { ...@@ -107,6 +107,7 @@ struct nvkm_outp_func {
struct { struct {
int (*aux_pwr)(struct nvkm_outp *, bool pu); int (*aux_pwr)(struct nvkm_outp *, bool pu);
int (*aux_xfer)(struct nvkm_outp *, u8 type, u32 addr, u8 *data, u8 *size);
} dp; } dp;
}; };
......
...@@ -25,6 +25,8 @@ ...@@ -25,6 +25,8 @@
#include "head.h" #include "head.h"
#include "ior.h" #include "ior.h"
#include <subdev/i2c.h>
#include <nvif/if0012.h> #include <nvif/if0012.h>
static int static int
...@@ -68,6 +70,20 @@ nvkm_uoutp_mthd_acquire_dp(struct nvkm_outp *outp, u8 dpcd[DP_RECEIVER_CAP_SIZE] ...@@ -68,6 +70,20 @@ nvkm_uoutp_mthd_acquire_dp(struct nvkm_outp *outp, u8 dpcd[DP_RECEIVER_CAP_SIZE]
return 0; 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 static int
nvkm_uoutp_mthd_dp_aux_pwr(struct nvkm_outp *outp, void *argv, u32 argc) 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) ...@@ -429,7 +445,7 @@ nvkm_uoutp_mthd_acquired(struct nvkm_outp *outp, u32 mthd, void *argv, u32 argc)
} }
static int 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) { switch (mthd) {
case NVIF_OUTP_V0_DETECT : return nvkm_uoutp_mthd_detect (outp, argv, argc); 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 ...@@ -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_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_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_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: default:
break; break;
} }
return 1; *invalid = true;
return 0;
} }
static int static int
...@@ -452,12 +470,13 @@ nvkm_uoutp_mthd(struct nvkm_object *object, u32 mthd, void *argv, u32 argc) ...@@ -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_outp *outp = nvkm_uoutp(object);
struct nvkm_disp *disp = outp->disp; struct nvkm_disp *disp = outp->disp;
bool invalid = false;
int ret; int ret;
mutex_lock(&disp->super.mutex); mutex_lock(&disp->super.mutex);
ret = nvkm_uoutp_mthd_noacquire(outp, mthd, argv, argc); ret = nvkm_uoutp_mthd_noacquire(outp, mthd, argv, argc, &invalid);
if (ret <= 0) if (!invalid)
goto done; goto done;
if (outp->ior) if (outp->ior)
......
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